Jest to raczej obserwacja, a także sugestia, jaki jest najlepszy sposób na obsłużenie tego scenariusza.sendto() dgrams nie blokują ENOBUFS na OSX
Mam dwa wątki, jeden po prostu pompuje dane, a drugi odbiera dane i wykonuje dużo pracy przed wysłaniem innego gniazda. Oba wątki są połączone za pośrednictwem gniazda domeny. Używany tutaj protokół to UDP. Nie chciałem używać TCP, ponieważ jest on oparty na strumieniu, co oznacza, że jeśli w kolejce jest mało miejsca, moje dane są dzielone i wysyłane. Jest to złe, ponieważ przesyłam dane, które nie powinny być dzielone. Dlatego użyłem DGRAM. Co ciekawe, gdy wątek wysyłania przytłacza wątek recv przez pompowanie tak dużej ilości danych, w pewnym momencie bufor gniazd domeny zostanie wypełniony, a sendto() zwróci ENOBUFS. Byłem zdania, że jeśli tak się stanie, sendto() będzie blokować, dopóki bufor nie będzie dostępny. To byłoby moje pożądane zachowanie. Jednak wydaje się, że tak nie jest. Rozwiązuję ten problem w dość dziwny sposób.
metoda Wydajność CPU Jeśli dostanę ENOBUFS, robię sched_yield(); jak nie ma pthread_yield() w OSX. Potem próbuję ponownie wysłać wiadomość. Jeśli to zawiedzie, robię to samo, dopóki nie zostanie zrobione. Jest to złe, ponieważ Iam marnuje cykle procesora, robiąc coś bezużytecznego. Bardzo bym chciał, gdyby sendto() było zablokowane.
Metoda uśpienia Próbowałem rozwiązać ten sam problem za pomocą trybu uśpienia (1) zamiast sched_yield(), ale to bezużyteczne jako funkcja uśpienia() uśpiłoby mój proces zamiast tylko tego wątku.
Obydwa z nich nie działają dla mnie i kończą się opcje. Czy ktoś może zasugerować jaki jest najlepszy sposób rozwiązania tego problemu? Czy istnieją jakieś sprytne sztuczki, których nie jestem w stanie uświadomić, które mogą zredukować niepotrzebne cykle procesora? btw, co strona człowiek mówi o sentto() jest błędne, na podstawie tej dyskusji http://lists.freebsd.org/pipermail/freebsd-hackers/2004-January/005385.html
Kodeksu Upd w jądrze:
The udp_output function in /sys/netinet/udp_usrreq.c, seems clear:
/*
* Calculate data length and get a mbuf
* for UDP and IP headers.
*/
M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
if (m == 0) {
error = ENOBUFS;
if (addr)
splx(s);
goto release;
}
Jak odradzasz wątki? W rzeczywistości [sleep (3)] (https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/sleep.3.html) powinno działać dla wątków POSIX. – artistoex