法楽日記

デジタル散策記&マインド探訪記

FreeBSD 11.1R: SOCK_NONBLOCK と SOCK_CLOEXEC

FreeBSD 11.1R では、socket() と socketpair() の第2引数 type でフラグを渡すことができるようになています。また新たなシステムコール accept4() の第4引数 flags でも同じようにフラグを渡すことができるようになっています。

かつては、socket() と socketpair() の第2引数 type で渡せるのは SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET の5種類でした。FreeBSD 11 では、type の値にフラグの値を論理ORすることで、type に加えてフラグを渡すことができるようになっています。現時点では SOCK_NONBLOCK と SOCK_CLOEXEC の2種類のフラグを渡すことができます。これらのマクロは sys/sys/socket.h で定義されています。

また、accept4() の第4引数 flags でもフラグとして同じく SOCK_NONBLOCK と SOCK_CLOEXEC の2種類のフラグを渡すことができるようになっています。

フラグのうち、SOCK_NONBLOCK は O_NONBLOCK / FNONBLOCK / FIONBIO と同じ意味で、SOCK_CLOEXEC は O_CLOEXEC と同じ意味です。詳しい使い方は「man 2 socket」、「man 2 socketpair」、「man 2 accept」をご覧ください。

カーネル内では kern_socket(), kern_socketpair(), kern_accept4() で処理されています。

Linuxマニュアルによると、Linux 2.6.27 から SOCK_NONBLOCK と SOCK_CLOEXEC がサポートされているそうです(Linux 2.6.27 は2008年10月にリリースされたそうです)。FreeBSD ではどのリリースからサポートされているかは調べられていませんが、下記コマンドの結果によると、実装が commit されたのは2013年3月です。

$ git show c9066bd014b20089911abc91a8c87ef738498a28

この2つのフラグ SOCK_NONBLOCK と SOCK_CLOEXEC がサポートされたことにより、重たいサーバで setsockopt() や ioctl() を1リクエストあたり1回ずつ減らせることが見込めます。「塵も積もれば山となる」を期待してのサポートだと思います。