Provided by: manpages-ja_0.5.0.0.20161015+dfsg-1_all 

名前
unix - ローカルな プロセス間通信用のソケット
書式
#include <sys/socket.h> #include <sys/un.h> unix_socket = socket(AF_UNIX, type, 0); error = socketpair(AF_UNIX, type, 0, int *sv);
説明
AF_UNIX (AF_LOCAL とも言われる) ソケットファミリーは、同じマシン上で プロセス同士が 効率的に通信するため に用いられる。伝統的に、UNIX ドメイン ソケットは、名前なしにもできるし、 (ソケット型であると印のついた) ファイル システムのパス名に 結び付けることもできる。さらに Linux では、ファイル システムに依存しない抽象 名前空間 (abstract namespace) もサポートしている。 UNIX ドメインに指定できるソケットタイプは以下の通りである。 SOCK_STREAM は、 ストリーム指向のソケットで有 効である。 SOCK_DGRAM は、 メッセージ境界を保存するデータグラム指向のソケットで有効である (ほとんどの UNIX の実装では、 UNIX ドメインデータグラムソケットは常に信頼でき、 データグラムの並び替えは行わない)。 SOCK_SEQPACKET は、 メッセージ境界を保存し送信された順序でメッセージを届ける接続指向ソケットで有効である (Linux 2.6.4 以降で利用できる)。 UNIX ドメインソケットでは、補助データを使って ファイルディスクリプターや プロセスの信任状 (credential) を 送受信することもできる。 アドレスのフォーマット UNIX ドメインソケットのアドレスは以下の構造体で表現される。 #define UNIX_PATH_MAX 108 struct sockaddr_un { sa_family_t sun_family; /* AF_UNIX */ char sun_path[UNIX_PATH_MAX]; /* pathname */ }; sun_family フィールドには必ず AF_UNIX が入っている。 様々なシステムコール (例えば bind(2), connect(2), sendto(2)) は入力として sockaddr_un 引き数を取る。 他の いくつかのシステムコール (例えば getsockname(2), getpeername(2), recvfrom(2), accept(2)) はこの型の引き数 を返す。 sockaddr_un 構造体では 3 種類のアドレスが区別される。 * pathname (パス名): bind(2) を使って、UNIX ドメインソケットを、 ヌル終端されたファイルシステム上のパス 名に結び付けることができる。 (上述のいずれかのシステムコールにより) ソケットのアドレスが返される際、 その長さは offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1 であり、 sun_path にはヌル終端されたパス名が格納される。 (Linux では、上記の offsetof() 式は sizeof(sa_family_t) の値と同じだが、 他の実装では sun_path の前に他のフィールドが含まれる場合もある。 そのため、 offsetof() 式を使う方がより移植性のある方法でアドレス構造体のサイズを知ることができる。) パス名ソケットの詳細については、後で説明する。 * unnamed (名前なし): bind(2) を使ってパス名に結び付けることができないストリーム型のソケットは 名前を持 たない。同様に、 socketpair(2) で作成される 2 つのソケットも名前を持たない。 名前なしのソケットのアド レスを返す際には、 その長さは sizeof(sa_family_t) であり、 sun_path は検査すべきではない。 * abstract (抽象): 抽象ソケットアドレスは、 sun_path[0] がヌルバイト ('\0') であることから (パス名ソケッ トから) 区別できる。 この名前空間におけるソケットのアドレスは、 sun_path の残りのバイトの、 アドレス構 造体の指定された長さの範囲で表される (名前中のヌルバイトには特別な意味はない)。 この名前はファイルシス テムのパス名とは何の関係もない。 抽象ソケットのアドレスを返される際には、 返される addrlen は sizeof(sa_family_t) より大きく (つまり 2 より大きく)、 ソケットの名前は sun_path の最初の (addrlen - sizeof(sa_family_t)) バイトに格納される。 ソケットの抽象名前空間は Linux による拡張であり、移植性はな い。 パス名ソケット ソケットにパス名を結びつける際に、 最大限の移植性を持たせ、コーディングを簡単にするためのルールがいくつか ある。 * sun_path のパス名はヌル終端すべきである。 * 終端のヌルバイトを含めたパス名の長さは sun_path の大きさを超えないようにすべきである。 * sockaddr_un 構造体の終わりを示す addrlen 引き数は最低でも以下の値を持つべきである。 offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1 もしくは、もっと簡単には、 addrlen に sizeof(struct sockaddr_un) を指定することもできる。 UNIX ドメインソケットアドレスの扱いが上記のルールに従っていない実装もいくつかある。 (全部ではないが) いく つかの実装では、 sun_path に文字列終端の NULL がなかった場合に終端の NULL が追加される。 移植性があるアプリケーションを作成する際には、 いくつかの実装では sun_path は 92 バイトしかないという点に も留意しておくとよい。 様々なシステムコール (accept(2), recvfrom(2), getsockname(2), getpeername(2)) がソケットアドレス構造体を 返す。 これらのシステムコールが UNIX ドメインソケットに対して呼ばれた際には、 これらの呼び出しに渡す addrlen 引き数は上記の説明のように初期化すべきである。 リターン時には、この引き数にはアドレス構造体の「実 際の」サイズが設定される。 呼び出し側ではこの引き数で返された値を確認すべきである。 返された値が入力値よ りも大きい場合、 sun_path に終端の NULL バイトが存在する保証はない (「バグ」を参照)。 ソケットオプション 歴史的な理由により、これらのオプションは たとえ AF_UNIX 固有のオプションであっても SOL_SOCKET 型で指定す る。 ソケットファミリーとして SOL_SOCKET を指定すると、 setsockopt(2) でオプションが設定でき、 getsockopt(2) で取得ができる。 SO_PASSCRED 送信プロセスの補助メッセージで信任状を受信できるようにする。このオプションが セットされていて、ま だソケットが接続されていないと、抽象名前空間に他と重なら ない名前が自動的に生成される。ブール整数 値のフラグを取る。 自動バインド (autobind) 機能 bind(2) 呼び出しで sizeof(sa_family_t) として addrlen を指定するか、 アドレスに明示的にバインドされていな いソケットに対して SO_PASSCRED ソケットオプションが指定されていた場合、 そのソケットは抽象アドレスに自動 的にバインドされる。 このアドレスは、1 個のヌルバイトの後に、文字集合 [0-9a-f] のバイトが 5 個続く形式で ある。したがって、自動的にバインドされるアドレス数には 2^20 個という上限が存在する。 (Linux 2.1.15 以降 で、自動バインド機能が追加されたときには、 8 バイトが使われており、自動バインドアドレス数の上限は 2^32 で あった。 Linux 2.3.15 で 5 バイトに変更された。) ソケット API この節では、Linux の UNIX ドメインソケットでの、ドメイン固有の詳細仕様と ソケット API でサポートされてい ない機能について説明する。 UNIX ドメインソケットでは、帯域外データ (out-of-band data) の 送信 (send(2) と recv(2) の MSG_OOB フラグ) はサポートされていない。 send(2) MSG_MORE フラグは UNIX ドメインソケットではサポートされていない。 recv(2) の flags 引き数での MSG_TRUNC の使用は UNIX ドメイン ソケットではサポートされていない。 SO_SNDBUF ソケットオプションは UNIX ドメインソケットで効果を持つが、 SO_RCVBUF は効果がない。 データグラ ムソケットでは、 SO_SNDBUF の値が 出力データグラムの上限サイズとなる。 実際の上限値は、 SO_SNDBUF オプ ション として設定された値の 2倍 (socket(7) 参照) からオーバヘッドとして使用される 32 バイトを引いた値とな る。 補助メッセージ 補助データを送受するには、 sendmsg(2) や recvmsg(2) を使用する。 歴史的な理由により、以下に示す補助メッ セージの型は たとえ AF_UNIX 固有のものであっても SOL_SOCKET 型で指定する。 これらを送るには、構造体 cmsghdr の cmsg_level フィールドに SOL_SOCKET をセットし、 cmsg_type フィールドにタイプをセットする。 詳 細は cmsg(3) を見よ。 SCM_RIGHTS 他のプロセスでオープンされたファイルディスクリプターのセットを送受信する。 データ部分にファイル ディスクリプターの整数配列が入っている。 渡されたファイルディスクリプターは、あたかも dup(2) で生 成されたかのように振る舞う。 SCM_CREDENTIALS UNIX 信任状を送受信する。これは認証に用いることができる。 信任状は struct ucred の補助メッセージと して渡される。 この構造体は <sys/socket.h> で以下のように定義されている。 struct ucred { pid_t pid; /* process ID of the sending process */ uid_t uid; /* user ID of the sending process */ gid_t gid; /* group ID of the sending process */ }; glibc 2.8 以降では、この構造体の定義を得るためには (どのヘッダーファイルをインクルードするよりも前 に) 機能検査マクロ _GNU_SOURCE を定義しなければならない。 送信側が指定した信任状は、カーネルがチェックする。 実効ユーザー ID が 0 のプロセスには、 自分自身 以外の値を指定する事が許される。 送信側は以下の 3 つを指定しなければならない。 1) 自分自身のプロセ ス ID (CAP_SYS_ADMIN 権限を持っていない場合)、 2) 自分自身のユーザー ID あるいは実効ユーザー ID か 保存 set-user-ID (CAP_SETUID 権限を持っていない場合)、 3) 自分自身のグループ ID あるいは実行グルー プ ID か保存 set-group-ID (CAP_SETGID を持っていない場合)。 struct ucred メッセージを受信するため には、ソケットに対し SO_PASSCRED オプションを有効にしなくてはならない。 ioctl 以下の ioctl(2) 呼び出しは value に情報を入れて返す。 正しい書式は以下の通り。 int value; error = ioctl(unix_socket, ioctl_type, &value); ioctl_type には以下を指定できる: SIOCINQ 受信バッファーのキューにある、まだ読んでいないデータの量を返す。ソケットは LISTEN 状態にあってはな らず、さもないとエラー (EINVAL) が返る。 SIOCINQ は <linux/sockios.h> で定義されている。 代わり に、<sys/ioctl.h> で定義されている、同義語の FIONREAD を使うこともできる。
エラー
EADDRINUSE 指定したローカルアドレスが既に使用されているか、ファイルシステムの ソケットオブジェクトが既に存在 している。 ECONNREFUSED connect(2) により指定されたリモートアドレスが接続待ちソケットではなかった。 このエラーはターゲット のパス名がソケットでなかった場合にも発生する。 ECONNRESET リモートソケットが予期しないかたちでクローズされた。 EFAULT ユーザーメモリーアドレスが不正。 EINVAL 渡した引数が不正。よくある原因としては、渡したアドレスの sun_type フィール ドに AF_UNIX が指定され ていなかった、行おうとした操作に対してソケットが有 効な状態ではなかった、など。 EISCONN 既に接続されているソケットに対して connect(2) が呼ばれた。または、指定したターゲットアドレスが 既 に接続済みのソケットだった。 ENOENT connect(2) に指定されたリモートアドレスのパス名が存在しなかった。 ENOMEM メモリーが足りない。 ENOTCONN ソケット操作にターゲットアドレスが必要だが、 このソケットは接続されていない。 EOPNOTSUPP ストリーム指向でないソケットに対してストリーム操作が呼び出された。 または帯域外データオプションを 用いようとした。 EPERM 送信者が struct ucred に不正な信任状を渡した。 EPIPE リモートソケットがストリームソケット上でクローズされた。 可能な場合は SIGPIPE も同時に送られる。こ れを避けるには MSG_NOSIGNAL フラグを sendmsg(2) や recvmsg(2) に渡す。 EPROTONOSUPPORT 渡されたプロトコルが AF_UNIX でない。 EPROTOTYPE リモートソケットとローカルソケットのタイプが一致していなかった (SOCK_DGRAM と SOCK_STREAM)。 ESOCKTNOSUPPORT 未知のソケットタイプ。 他にも汎用のソケット層でエラーが起こったり、 ファイルシステム上にソケットオブジェクトを作ろうとした場合に ファイルシステムのエラーが起こることがある。 それぞれの詳細は適切な man ページを参照すること。
バージョン
SCM_CREDENTIALS と抽象名前空間は、Linux 2.2 で導入された。 移植性が必要なプログラムでは使うべきではない。 (BSD 由来のシステムの中にも信任状の送受信をサポートしているものがあるが、 その実装の詳細はシステムによっ て異なる)
注意
Linux の実装では、 ファイルシステム上から見えるソケットは、 それらが置かれているディレクトリのパーミッ ションに従う。 ソケットの所有者、 グループ、 パーミッションは変更できる。 新しいソケットを作るとき、 作ろ うとするディレクトリに対して プロセスが書き込みと検索 (実行) 権限を持っていなければ、 作成に失敗する。 ソ ケットオブジェクトに接続するには、 read/write 権限が必要である。 この動作は、 多くの BSD 由来のシステムと は異なっている (BSD では UNIX ドメインソケットに対してはパーミッションを無視する)。 移植性の必要なプログ ラムでは、セキュリティをこの仕様に依存してはならない。 ファイル名を指定してソケットにバインドすると、ファイルシステムにソケットが 生成される。これは必要なくなっ たときに呼びだしたユーザーが削除しなければ ならない (unlink(2) を用いる)。 UNIX で通常使われる「背後で閉 じる方式」 が適用される。ソケットはいつでも unlink することができ、最後の参照が クローズされたときにファ イルシステムから削除される。 SOCK_STREAM 上でファイルディスクリプターや信任状を渡すためには、同じ sendmsg(2) や recvmsg(2) コールで補 助データ以外のデータを少なくとも 1 バイト送信/受信する必要がある。 UNIX ドメインのストリームソケットでは、 帯域外データの概念はサポートされない。
バグ
ソケットをアドレスに結びつける際、 Linux は終端の NULL が sun_path になかった場合に追加する実装の一つであ る。 ほとんどの場合、 これは問題にならない。 ソケットアドレスが取得された際、ソケットをバインドしたときに 指定したものより 1 バイト長くなるだけである。 しかしながら、紛らわしい動作が起こる場合が一つある。 ソケッ トをバインドした際に 108 個の NULL でないバイトを指定した場合、 終端の NULL が追加されるとパス名の長さが sizeof(sun_path) を超えてしまう。 結果として、(例えば accept(2) で) ソケットアドレスを取得した際に、 値を 取得する呼び出しの入力の address 引き数に sizeof(struct sockaddr_un) を指定したとすると、 返されるアドレ ス構造体は sun_path に終端の NULL を「含まない」ことになる。 さらに、 いくつかの実装では、ソケットをバインドする際に終端の NULL が必要ではなく (addrlen 引き数を使って sun_path の長さが判定される)、 このような実装でソケットアドレスを取得する際には、 sun_path に終端の NULL は存在しない。 ソケットアドレスを取得するアプリケーションでは、 sun_path に終端の NULL が存在しないという移植性の問題 を、 パス名の有効なバイト数が以下のようになると事実を考慮することで取り扱うことができる。 strnlen(addr.sun_path, addrlen - offsetof(sockaddr_un, sun_path)) 他の方法としては、 アプリケーションがソケットアドレスを取得する際、 取得の呼び出しを行う前に、 大きさが sizeof(struct sockaddr_un)+1 のバッファーを割り当てることもできる。 取得の呼び出しでは addrlen に sizeof(struct sockaddr_un) を指定すると、 余分な一つの 0 バイトにより sun_path で返される文字列に終端の NULL が含まれることが保証される。 void *addrp; addrlen = sizeof(struct sockaddr_un); addrp = malloc(addrlen + 1); if (addrp == NULL) /* Handle error */ ; memset(addrp, 0, addrlen + 1); if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1) /* handle error */ ; printf("sun_path = %s\n", ((struct sockaddr_un *) addrp)->sun_path); アプリケーションが「パス名ソケット」の節で説明したルールにしたがってパス名を「作成」していれば、 このよう な分かりにくさは避けることができる。
例
bind(2) 参照。 SCM_RIGHTS の使用例については cmsg(3) を参照。
関連項目
recvmsg(2), sendmsg(2), socket(2), socketpair(2), cmsg(3), capabilities(7), credentials(7), socket(7)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告 に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。