UNIX engellemesiz G / Ç: O_NONBLOCK - FIONBIO


92

Ben BSD soket programlama bağlamında üzerinde çalıştırmak her örnekte ve tartışmada, o I tıkanmasızdır için bir dosya tanıtıcı set önerilen yoludur / Ç modu kullandığını görünüyor O_NONBLOCKbayrağı için fcntl(), örneğin,

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

On yılı aşkın süredir UNIX'te ağ programlama yapıyorum ve her zaman FIONBIO ioctl()bunu yapmak için çağrıyı kullandım :

int opt = 1;
ioctl(fd, FIONBIO, &opt);

Asla nedenini pek düşünmedim. Sadece bu şekilde öğrendim.

Birinin veya diğerinin olası yararları hakkında herhangi bir yorumu olan var mı? Taşınabilirlik lokusunun biraz farklı olduğunu hayal ediyorum, ancak ioctl_list(2)bireysel ioctlyöntemlerin bu yönüne ne ölçüde hitap etmediğini bilmiyorum .

Yanıtlar:


137

Standardizasyondan önce ioctl(... FIONBIO... )ve fcntl(... O_NDELAY... vardı ), ancak bunlar sistemler arasında ve hatta aynı sistem içinde tutarsız davrandı. Örneğin, borular, ellikler ve cihazlar gibi şeyler için pek çok tutarsızlıkla FIONBIOsoketler üzerinde O_NDELAYçalışmak ve tty'ler üzerinde çalışmak yaygındı . Ve ne tür bir dosya tanımlayıcınız olduğunu bilmiyorsanız, emin olmak için ikisini de ayarlamanız gerekir. Ancak ek olarak, mevcut veri olmadan bloke edici olmayan bir okuma da tutarsız bir şekilde belirtildi; İşletim sistemine ve dosya tanımlayıcısının türüne bağlı olarak okuma, EAGAIN hatasıyla 0 veya -1 veya EWOULDBLOCK hatasıyla -1 döndürebilir. Bugün bile, ayar FIONBIOveyaO_NDELAYon Solaris, veri içermeyen bir okumanın bir tty veya boru üzerinde 0 veya bir soket üzerinde EAGAIN hatası ile -1 döndürmesine neden olur. Ancak 0, EOF için de döndürüldüğünden belirsizdir.

POSIX O_NONBLOCK, farklı sistemler ve dosya tanımlayıcı türleri arasında standart davranışa sahip olanın tanıtımıyla bu sorunu çözdü . Mevcut sistemler genellikle geriye dönük uyumluluğu bozabilecek herhangi bir davranış değişikliğinden kaçınmak istediğinden, POSIX diğerlerinden biri için belirli bir davranışı zorunlu kılmak yerine yeni bir bayrak tanımladı. Linux gibi bazı sistemler 3'e de aynı şekilde davranır ve ayrıca EAGAIN ve EWOULDBLOCK'u aynı değere tanımlar, ancak geriye dönük uyumluluk için diğer bazı eski davranışları sürdürmek isteyen sistemler, eski mekanizmalar kullanıldığında bunu yapabilir.

Yeni programlar , POSIX tarafından standartlaştırıldığı gibi fcntl(... O_NONBLOCK... kullanmalıdır ).


6
Bunun için ioctl () kullanma eğilimindeyim çünkü bloke edici olmayan modu etkinleştirmek için fcntl () için iki yerine yalnızca bir sistem çağrısına mal oluyor. Ek olarak, Windows ioctlsocket () API, bu işlevselliğin amaçları açısından ioctl () ile eşdeğerdir.
Wez Furlong

nginx yapabiliyorsa bunu yapar ve "ioctl (FIONBIO) tek sistem çağrısıyla engellemesiz bir mod ayarlar" yorumuyla işaretler. Şimdi, bir bağlantıyı kabul etmenize ve aynı sistem çağrısında onu engellemesiz moda geçirmenize izin veren kabul2 var.
Eloff

6

@Sean'ın dediği gibi fcntl(), büyük ölçüde standartlaştırılmıştır ve bu nedenle platformlar arasında kullanılabilir. ioctl()Fonksiyon öncedir fcntl()Unix, ama hiç standart değil. ioctl()Sizinle alaka düzeyinin tüm platformlarında sizin için çalışmış olması bir şans, ancak garanti edilemiyor. Özellikle, ikinci argüman için kullanılan isimler gizlidir ve platformlar arasında güvenilir değildir. Aslında, genellikle dosya tanımlayıcısının başvurduğu belirli aygıt sürücüsüne özgüdürler. ( ioctl()Örneğin, yirmi yıl önce PNX (Perq Unix) çalıştıran bir ICL Perq üzerinde çalışan bit eşlemli bir grafik aygıtı için kullanılan çağrılar, başka herhangi bir yere asla çevrilmedi.)


5

fcntl()Bir POSIX işlevi olduğuna inanıyorum . Nerede olarak ioctl()standart bir UNIX şeydir. İşte POSIX io listesi . ioctl()çok çekirdek / sürücü / işletim sistemine özgü bir şey, ancak kullandığınız şeyin Unix'in çoğu çeşidinde işe yaradığından eminim. diğer bazı ioctl()şeyler yalnızca belirli işletim sistemlerinde veya hatta çekirdeğin belirli devirlerinde çalışabilir.


FIONBIO'yu AIX, Solaris, Linux, * BSD ve IRIX üzerinde sorunsuz kullandım. Ama evet, bunun Windows üzerinde çalışmayacağını anlıyorum, örneğin - çok özel bir çekirdek uygulaması için düşük seviyeli bir arayüz. Yine de, farklılaştıran başka faktörler olup olmadığını merak ediyorum.
Alex Balashov
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.