UNIX blokuoja I / O: O_NONBLOCK vs. FIONBIO

Kiekviename pavyzdyje ir diskusijoje, kurią žiūriu BSD lizdų programavimo kontekste, atrodo, kad rekomenduojamas būdas nustatyti failo deskriptorių į ne blokavimo I / O režimą naudoja „ O_NONBLOCK vėliavą fcntl() , pvz.

 int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); 

Aš jau daugiau nei dešimt metų FIONBIO ioctl() programuojant UNIX ir visada naudoju FIONBIO ioctl() kvietimą tai padaryti:

 int opt = 1; ioctl(fd, FIONBIO, > 

Aš niekada nemaniau, kodėl. Tiesiog sužinojote.

Ar kas nors turi pastabų dėl galimų atitinkamų vieno ar kito privalumų? Manau, kad perkėlimo lokusas yra šiek tiek kitoks, bet nežinau, kaip ioctl_list(2) apie šį atskirų ioctl metodų aspektą nekalbama.

78
19 июля '09 в 22:17 2009-07-19 22:17 Alex Balashov užduodamas liepos 19 d., 09:17 val. 2009-07-19 22:17
@ 3 atsakymai

Prieš standartizavimą buvo ioctl( ... FIONBIO ... ) ir fcntl( ... O_NDELAY ... ) , tačiau jie buvo nesuderinami tarp sistemų ir net toje pačioje sistemoje. Pavyzdžiui, „ FIONBIO buvo nuspręsta dirbti su lizdais ir „ O_NDELAY “ darbui su ttys, su daugybe neatitikimų tokiems dalykams kaip vamzdžiai, pataisymai ir įrenginiai. Ir jei nežinote, kurį failo aprašą turėjote, turėsite nustatyti abu. Be to, netinkamai buvo užfiksuotas ir neskaitymas be duomenų. priklausomai nuo OS ir failų deskriptoriaus tipo, skaitymas gali grąžinti 0 arba -1 su errno EAGAIN arba -1 su errno EWOULDBLOCK. Net ir šiandien „ FIONBIO arba „ O_NDELAY „Solaris“ sukelia skaitymą be jokių duomenų grįžti į „0“ į „tty“ arba „vamzdį“ arba -1 su „errno EAGAIN“ lizde. Tačiau 0 yra dviprasmiškas, nes jis taip pat grąžinamas EOF.

POSIX šią problemą sprendė įvedus O_NONBLOCK , kuris turi standartizuotą elgesį įvairiose sistemose ir failų aprašų tipuose. Kadangi esamos sistemos paprastai nori išvengti bet kokių elgesio pokyčių, kurie gali pažeisti atgalinį suderinamumą, POSIX apibrėžė naują vėliavą, o ne įgaliojimą tam tikram kitam elgesiui. Kai kurios sistemos, pvz., „Linux“, traktuoja visus 3 vienodai, taip pat apibrėžia EAGAIN ir EWOULDBLOCK tą pačią vertę, bet sistemos, norinčios išlaikyti kitas paveldėtas savybes, kad būtų galima suderinti atgal, gali tai padaryti, kai naudojami senesni mechanizmai.

Naujos programos turėtų naudoti fcntl( ... O_NONBLOCK ... ) kaip standartizuotą POSIX.

113
20 июля '09 в 1:37 2009-07-20 01:37 atsakymas pateikiamas „ mark4o“ liepos 20 d., „09“, 1:37 2009-07-20 01:37

Manau, kad fcntl() yra POSIX funkcija. Kur ioctl() yra standartinis UNIX dalykas. Toliau pateikiamas POSIX io sąrašas. ioctl() yra labai specifinis dalykas branduoliui / vairuotojui / operacinei sistemai, bet esu tikras, kad jį naudosite, jis veikia daugelyje „Unix“ skonių. kai kurie kiti „ ioctl() dalykai gali veikti tik su tam tikra OS arba net su kai kuriomis branduolio revoliucijomis.

5
19 июля '09 в 22:36 2009-07-19 22:36 atsakymą pateikė EdH, liepos 19 d., 09:36 , 10:36 val. 2009-07-19 22:36

Kaip sakė @Sean, fcntl() yra iš esmės standartizuotas ir todėl prieinamas įvairiose platformose. „ ioctl() funkcija pirmyn fcntl() Unix sistemoje, bet visai nėra standartizuota. Tai, kad „ ioctl() dirbo jums visose svarbiose platformose, yra sėkmingesnis, bet neužtikrintas. Visų pirma antrajam argumentui naudojami pavadinimai yra slapti ir nepatikimi tarp platformų. Iš tiesų, jie dažnai yra unikalūs konkrečiam įrenginio tvarkyklei, su kuria susiję failų aprašai. („ ioctl() skambutis, naudojamas dvigubai susietam grafikos įrenginiui, veikiančiam Perl ICL, dirbant su PNX (Perq Unix) prieš dvidešimt metų niekada nebuvo išverstas niekur kitur.)

4
19 июля '09 в 23:25 2009-07-19 23:25 atsakymą pateikė Jonathan Leffler liepos 19 d., 09:25, 23:25

Peržiūrėkite kitus klausimus apie žymes arba Užduokite klausimą