UNIXドメインソケット

UNIXドメインソケットは単一マシン上の高効率なプロセス間通信に用いられる機能・インタフェースの一種である。

プロセス間通信  は一般的に名前付きパイプやBSDソケットを利用したTCP通信などで実現できる。UNIXドメインソケットはBSDソケットの一種であり、単一マシン上でのプロセス間通信を目的としている。ソケット通信がもつ双方性・プロセスfork不要といった特徴を備えつつ、単一マシン上の通信であることを生かした高効率な通信を可能にしている。

UNIXドメインソケットは、アドレス・名前空間としてファイルシステムを使用している。これらは、ファイルシステム内のinodeとしてプロセスから参照される。これは、2つのプロセスが通信するために、同じソケットを開くことができる。しかし、コミュニケーションは、完全にオペレーティングシステムのカーネル内で発生する。データを送ることに加えて、プロセスは、sendmsgおよびrecvmsgシステムコールを使用してUNIXドメインソケット接続を経由してファイル記述子を送信することができる。

POSIXはBSDソケットとしてUNIXドメインソケットインタフェースを提供している。BSDソケットのAF_UNIXprotocol familyがUNIXドメインソケットに相当する。受け入れ可能なsocket typeはSOCK_STREAM・SOCK_DGRAM・SOCK_SEQPACKETの3種類である。

Go言語では、Microsoft Windows上でもUNIXドメインソケットを使ったプログラムを動かすことができる。

特殊なUNIXドメインソケットとして、socketpairを用いて作られるものがある。socketpairはUNIXドメインソケットを2点作成し、一方のソケットに書き込んだデータがもう一方のソケットから読み出せる。パイプが一方通行の読み書きしかできないのに対し、socketpairにて作成したソケットでは双方向通信が可能である。

1. 利用方法
-------

1.1. C言語
--------

socket 関数における第1引数の domain に AF_UNIX を指定する。第2引数の type は SOCK_STREAM, SOCK_DGRAM どちらも利用可能。そして、クライアント側の場合、その後 connect を呼ぶ。

1.2. Java
---------

以下のライブラリなどで利用可能。

[1]
[2]また、JEP380によりJava 16よりjava.nio.channels.SocketChannelで利用可能

1.3. Android
------------

Android SDKに、Java/Kotlinから利用できる android.net.LocalSocket クラスが実装されている。

1.4. Mono
---------

Mono.Unix.UnixClient クラスで利用可能。

1.5. PHP
--------

URL を unix:// もしくは udg:// で始めることで利用可能。

2. ソースコード例
----------

2.1. サーバ
--------

C99 でのサーバ側のソースコード例は以下の通り。

include
include
include
include <sys/types.h>
include <sys/socket.h>
include <sys/un.h>int main { // サーバーソケット作成 int sock = socket; if  { perror; return 1; }

// struct sockaddr_un 作成 struct sockaddr_un sa = {0}; sa.sun_family = AF_UNIX; strcpy;

// 既に同一ファイルが存在していたら削除 remove;

// バインド if  &sa, sizeof) == -1) { perror; goto bail; }

// リッスン if  == -1) { perror; goto bail; }

while  { // クライアントの接続を待つ int fd = accept; if  { perror; goto bail; }

// 受信 char buffer[4096]; int recv_size = read - 1); if  { perror; close; goto bail; }

// 受信内容を表示 buffer[recv_size] = '\0'; printf;

// ソケットのクローズ if  == -1) { perror; goto bail; } }

bail: // エラーが発生した場合の処理 close; return 1; }<WtXmlEndTag />

2.2. クライアント
-----------

C99 でのクライアント側のソースコード例は以下の通り。

include
include
include
include <sys/types.h>
include <sys/socket.h>
include <sys/un.h>
define MESSAGE "Hello World!"int main { // ソケット作成 int sock = socket; if  { perror; return 1; }

// struct sockaddr_un 作成 struct sockaddr_un sa = {0}; sa.sun_family = AF_UNIX; strcpy;

// 接続 if  &sa, sizeof) == -1) { perror; goto bail; }

// 送信 if ) == -1) { perror; goto bail; }

// クローズ close; return 0;

bail: // エラーが発生した場合の処理 close; return 1; }<WtXmlEndTag />

3. 実装
-----

3.1. Linux
----------

LinuxカーネルにBSDソケット AF_UNIXprotocol familyとして実装されている。SOCKETをはじめとするシステムコールをAPIとして公開している。

3.1.1. 内部実装
-----------

LinuxにおけるUNIXドメインソケットは、バッファへの書き込みと読み込みという非常にシンプルな仕組みで実装されている。

Linuxカーネルのlinux/net/unix/af_unix.c  に実装される。SOCK_STREAMの場合、カーネル内部ではソケットバッファへのメッセージコピー・peerがもつsk_receive_queueのtail、受信側のsk_data_ready呼び出し、を繰り返すことでデータを転送する。

UNIXドメインソケットは単一マシン上のIPCが前提である。ゆえにTCPのようなプロトコルスイートは不要であり、プロトコルの重層が生むデータの入れ子構造を持たない。またネットワークに由来するパケットロスや到達順序保証の対応も必要ないため、バッファのread/writeというシンプルな仕組みで実装されている。結果として高効率なIPCが可能となっている。

4. 脚注
-----

5. 関連項目
-------

ソケット 

6. 外部リンク
--------

仕様
[4]
[5], UNIXドメインソケット クライアントサーバー コマンドラインツール
解説
[6]
Robert Watson  [7]