これは観察であり、このシナリオを処理する最善の方法についての提案でもあります。
私は 2 つのスレッドを持っています。1 つはデータを送り込むだけで、もう 1 つはデータを受信し、別のソケットを送信する前に多くの作業を行います。両方のスレッドは、ドメイン ソケットを介して接続されます。ここで使用されるプロトコルは UDP です。TCP はストリーム ベースであるため、使用したくありませんでした。つまり、キューにほとんどスペースがない場合、データは分割されて送信されます。分割してはならないデータを送信しているため、これは悪いことです。したがって、DGRAM を使用しました。興味深いことに、送信スレッドが非常に多くのデータをポンピングして recv スレッドを圧倒すると、ある時点でドメイン ソケット バッファがいっぱいになり、sendto() が ENOBUFS を返します。これが発生した場合、sendto() はバッファーが使用可能になるまでブロックされるという意見でした。これは私の望ましい動作です。しかし、そうではないようです。私はこの問題をかなり奇妙な方法で解決します。
CPU Yield メソッド ENOBUFS を取得したら、sched_yield(); を実行します。OSX には pthread_yield() がないためです。その後、再送を試みます。それが失敗した場合、私はそれが取られるまで同じことを続けます. 役に立たないことをしているだけでCPUサイクルを浪費しているので、これは悪いことです。sendto() がブロックされれば幸いです。
スリープメソッド sched_yield() の代わりに sleep(1) を使用して同じ問題を解決しようとしましたが、sleep() は送信スレッドだけでなくプロセスをスリープ状態にするため、これは役に立ちません。
どちらも私にはうまくいかないようで、オプションが不足しています。誰かがこの問題を処理する最善の方法を提案できますか? 不要な CPU サイクルを減らすことができる、私が気付いていない巧妙なトリックはありますか? ところで、man ページがsendto () について述べていることは、この議論に基づいて間違っています
カーネルの Upd コード:
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;
}