UNIXドメインソケット

UNIXドメインソケット（）は単一マシン上の高効率なプロセス間通信に用いられる機能・インタフェースの一種である。
プロセス間通信 (Inter-Process Communication: IPC) は一般的に名前付きパイプやBSDソケットを利用したTCP通信などで実現できる。UNIXドメインソケットはBSDソケットの一種であり、単一マシン上でのプロセス間通信を目的としている。ソケット通信がもつ双方性・プロセスfork不要といった特徴を備えつつ、単一マシン上の通信である（=インターネットを介さない）ことを生かした高効率な通信を可能にしている。
UNIXドメインソケットは、アドレス・名前空間としてファイルシステムを使用している。これらは、ファイルシステム内のinodeとしてプロセスから参照される。これは、2つのプロセスが通信するために、同じソケットを開くことができる。しかし、コミュニケーションは、完全にオペレーティングシステムのカーネル内で発生する。データを送ることに加えて、プロセスは、codice_1およびcodice_2システムコールを使用してUNIXドメインソケット接続を経由してファイル記述子を送信することができる。 
POSIXはBSDソケットとしてUNIXドメインソケットインタフェースを提供している。BSDソケットのcodice_3protocol familyがUNIXドメインソケットに相当する。受け入れ可能なsocket typeはcodice_4・codice_5・codice_6の3種類である。
Go言語（の実行環境）では、Microsoft Windows上でもUNIXドメインソケットを使ったプログラムを動かすことができる。
利用方法.
C言語.
codice_7 関数における第1引数の domain に codice_3 を指定する。第2引数の type は codice_4, codice_5 どちらも利用可能。そして、クライアント側の場合、その後 codice_11 を呼ぶ。
Java.
以下のライブラリなどで利用可能。
また、JEP380によりJava 16よりcodice_12で利用可能
Android.
Android SDKに、Java/Kotlinから利用できる codice_13 クラスが実装されている。
Mono.
codice_14 クラスで利用可能。
PHP.
URL を unix:// もしくは udg:// で始めることで利用可能。
ソースコード例.
サーバ.
C99 でのサーバ側のソースコード例は以下の通り。
int main(void)
 // サーバーソケット作成
 int sock = socket(AF_UNIX, SOCK_STREAM, 0);
 if (sock == -1)
 perror("socket");
 return 1;
 // struct sockaddr_un 作成
 struct sockaddr_un sa = {0};
 sa.sun_family = AF_UNIX;
 strcpy(sa.sun_path, "/tmp/unix-domain-socket");
 // 既に同一ファイルが存在していたら削除
 remove(sa.sun_path);
 // バインド
 if (bind(sock, (struct sockaddr*) &sa, sizeof(struct sockaddr_un)) == -1)
 perror("bind");
 goto bail;
 // リッスン
 if (listen(sock, 128) == -1)
 perror("listen");
 goto bail;
 while (1)
 // クライアントの接続を待つ
 int fd = accept(sock, NULL, NULL);
 if (fd == -1)
 perror("accept");
 goto bail;
 // 受信
 char buffer[4096];
 int recv_size = read(fd, buffer, sizeof(buffer) - 1);
 if (recv_size == -1)
 perror("read");
 close(fd);
 goto bail;
 // 受信内容を表示
 buffer[recv_size] = '\0';
 printf("message: %s\n", buffer);
 // ソケットのクローズ
 if (close(fd) == -1)
 perror("close");
 goto bail;
bail:
 // エラーが発生した場合の処理
 close(sock);
 return 1;
クライアント.
C99 でのクライアント側のソースコード例は以下の通り。
int main(void)
 // ソケット作成
 int sock = socket(AF_UNIX, SOCK_STREAM, 0);
 if (sock == -1)
 perror("socket");
 return 1;
 // struct sockaddr_un 作成
 struct sockaddr_un sa = {0};
 sa.sun_family = AF_UNIX;
 strcpy(sa.sun_path, "/tmp/unix-domain-socket");
 // 接続
 if (connect(sock, (struct sockaddr*) &sa, sizeof(struct sockaddr_un)) == -1)
 perror("connect");
 goto bail;
 // 送信
 if (write(sock, MESSAGE, strlen(MESSAGE)) == -1)
 perror("write");
 goto bail;
 // クローズ
 close(sock);
 return 0;
bail:
 // エラーが発生した場合の処理
 close(sock);
 return 1;
実装.
Linux.
LinuxカーネルにBSDソケット codice_3protocol familyとして実装されている。SOCKET(2)をはじめとするシステムコールをAPIとして公開している。
内部実装.
LinuxにおけるUNIXドメインソケットは、バッファ（メモリ）への書き込みと読み込みという非常にシンプルな仕組みで実装されている。
Linuxカーネルのcodice_16 (GitHub mirror) に実装される。codice_4の場合、カーネル内部ではソケットバッファへのメッセージコピー・peerがもつcodice_18のtail、受信側のcodice_19呼び出し、を繰り返すことでデータを転送する。
UNIXドメインソケットは単一マシン上のIPCが前提である。ゆえにTCPのようなプロトコルスイートは不要であり、プロトコルの重層が生むデータの入れ子構造を持たない。またネットワークに由来するパケットロスや到達順序保証の対応も必要ないため、バッファのread/writeというシンプルな仕組みで実装されている。結果として高効率なIPCが可能となっている。