「UNIXドメインソケット」の版間の差分
→関連項目: +reflist |
|||
30行目: | 30行目: | ||
[[C99]] でのサーバ側のソースコード例は以下の通り。 |
[[C99]] でのサーバ側のソースコード例は以下の通り。 |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
107行目: | 107行目: | ||
return 1; |
return 1; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
=== クライアント === |
=== クライアント === |
||
[[C99]] でのクライアント側のソースコード例は以下の通り。 |
[[C99]] でのクライアント側のソースコード例は以下の通り。 |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
160行目: | 160行目: | ||
return 1; |
return 1; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
== 実装 == |
== 実装 == |
2020年7月5日 (日) 23:05時点における版
UNIXドメインソケット(英: UNIX domain socket)は単一マシン上の高効率なプロセス間通信に用いられる機能・インターフェースの一種である[1]。
プロセス間通信は名前付きパイプやBSDソケットを利用したTCP通信などで実現できる。UNIXドメインソケットはBSDソケットの一種であり、単一マシン上でのプロセス間通信を目的としている。ソケット通信がもつ双方性・プロセスfork不要といった特徴を備えつつ、単一マシン上の通信である(=インターネットを介さない)ことを生かした高効率な通信を可能にしている。
UNIXドメインソケットは、アドレス・名前空間としてファイルシステムを使用している。これらは、ファイルシステム内のinodeとしてプロセスから参照される。これは、2つのプロセスが通信するために、同じソケットを開くことができる。しかし、コミュニケーションは、完全にオペレーティングシステムのカーネル内で発生する。データを送ることに加えて、プロセスは、sendmsg() およびrecvmsg() システムコールを使用してUNIXドメインソケット接続を経由してファイル記述子を送信することができる。
POSIXはBSDソケットとしてUNIXドメインソケットインターフェースを提供している。BSDソケットのAF_UNIX
protocol familyがUNIXドメインソケットに相当する[2]。受け入れ可能なsocket typeはSOCK_STREAM
・SOCK_DGRAM
・SOCK_SEQPACKET
の3種類である。
利用方法
C言語
socket()
で第1引数の domain に AF_UNIX
を指定する。第2引数の type は SOCK_STREAM
, SOCK_DGRAM
どちらも利用可能。そして、クライアント側の場合、その後 connect()
を呼ぶ。
Java
以下のライブラリなどで利用可能。
Android (Java)
android.net.LocalSocket
クラスで利用可能。
Mono
Mono.Unix.UnixClient
クラスで利用可能。
PHP
URL を unix:// もしくは udg:// で始めることで利用可能。
ソースコード例
サーバ
C99 でのサーバ側のソースコード例は以下の通り。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
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 でのクライアント側のソースコード例は以下の通り。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define MESSAGE "Hello World!"
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ソケット AF_UNIX
protocol familyとして実装されている。SOCKET(2)をはじめとするシステムコールをAPIとして公開している。
内部実装
LinuxにおけるUNIXドメインソケットは、バッファ(メモリ)への書き込みと読み込みという非常にシンプルな仕組みで実装されている。
Linuxカーネルのlinux/net/unix/af_unix.c
(GitHub mirror)に実装される。SOCK_STREAM
の場合、カーネル内部ではソケットバッファへのメッセージコピー・peerがもつsk_receive_queue
のtail、受信側のsk_data_ready
呼び出し、を繰り返すことでデータを転送する。
UNIXドメインソケットは単一マシン上のIPCが前提である。ゆえにTCPのようなプロトコルスイートは不要であり、プロトコルの重層が生むデータの入れ子構造を持たない。またネットワークに由来するパケットロスや到達順序保証の対応も必要ないため、バッファread/writeというシンプルな仕組みで実装されている。結果として高効率なIPCが可能となっている。
脚注
関連項目
外部リンク
- 仕様
- UNIX(7) Linux Programmer's Manual
socketpair
– The Open Group基本仕様書第7号2018年版「システムインターフェース」sendmsg
– The Open Group基本仕様書第7号2018年版「システムインターフェース」recvmsg
– The Open Group基本仕様書第7号2018年版「システムインターフェース」
cmsg(3)
– JM Project Linux Library Functions マニュアル- ucspi-unix, UNIXドメインソケット クライアントサーバー コマンドラインツール
- 解説
- Beej's Guide to Unix IPC - Unix Sockets
- Robert Watson (2005) "UNIXドメインソケット vs インターネットソケット"