web-dev-qa-db-ja.com

Unixドメインソケットバインド、アドレスの再利用

bind()AF_INETソケット(TCP接続の場合)の場合、後でclose() itにすると、次にプログラムを実行するときに問題が発生する可能性があります、close()にもかかわらず、カーネルは開いたソケットに関連付けられたリソースをまだ持つことができます。

ただし、Unix Domain Socketsでのこの問題についてはあまり明確ではありません。

これまでに見た

  1. bind()で使用するには、一意のパスが必要です。パスはbind()が呼び出されるときに存在していてはならず、ファイルはbind()によって作成されます。 (ただし、ファイルシステムに表示される場合と表示されない場合があります。パスが特殊文字\0で始まる場合、ファイルはファイルシステムに表示されません。)

  2. ファイルがunlink()- edでない場合、閉じた後でも、カーネルは関連するリソースを保持しており、ソケットは完全に機能しています。

質問:

close()unlink()もUnixドメインソケットを非表示にすることはできないので、どちらもトリックを確実に実行します/ソケットに関連付けられているすべてのリソースを放棄するようにカーネルをトリガーしますか?

close()unlink()の両方が呼び出された場合、reuseaddrエラーが発生する可能性はありますか?


編集(コメントと回答の後):

したがって、バインドされたAF_LOCALソケットは次のようになります。

unix_domain_socket_inode
-> binded to a socket
-> associated with a file (path)

unix_domain_socket_inodeは、次の条件を満たす限り存続します。

  1. 何かが開いたままにしている(ソケットが閉じていない)、または
  2. 関連するパスがあります

1.のみがtrueの場合、オープンソケットとiノードがあり、すべてが機能します。

2.のみがtrueの場合、iノードにパスが関連付けられているため、カーネルはそれをクリーンアップできませんが、着信接続を処理するソケットリソースが不足しているため機能しません。それは通常のファイルではなく、ビジーで動作するソケットの過去の栄光の死んだ殻に過ぎません。

AF_INET接続の場合、アドレスの再利用の問題は、使いやすさを高めるための設計上の選択でした。

AF_LOCALの場合、残りのファイルは以前の設計選択からのアーティファクトであり、close()が呼び出されたときにカーネル自体が1回で作成したファイルを自動的にクリーンアップできなくなります。 close()が呼び出された後、カーネルがこのリソースを保持する必要があるため、関連する隠されたメカニズムはありません。

4
Zoltan K.

この文脈では、カーネルがTCP接続のTIME_WAIT状態を持っている理由の根拠を理解することが重要です。この状態は、接続に関連付けられたパケット(同じポートで新しい接続を確立する前に、より長いルートをとるか、遅延してネットワークから流出します。これにより、新しい接続が古い接続に関連付けられたパケットを受信しないようにすることができます。reuseaddrオプションを使用すると、開発者は「その待機を行わない」ことを伝えることができます。

Unixドメインソケットはそのような懸念はありません。 reuseaddrはそのコンテキストでは実際には意味がありません。

3
Andy Dalton

ファイルがunlink()されていない場合、閉じた後でも、カーネルは関連するリソースを保持し、ソケットは完全に機能します。

いいえ、カーネルは、最後に開いたハンドルがclose()dであったときに、ソケットに関連付けられたすべてのリソースを解放します。再度bind()できるようにするには、パスをunlink()するだけです。

Close()もunlink()もUnixドメインソケットを非表示にすることはできないので、どちらもトリックを確実に実行します/ソケットに関連付けられているすべてのリソースを放棄するようにカーネルをトリガーしますか?

上記を参照 ;-)

Unix_domain_socket_inodeは、次の条件を満たす限り存続します。

  1. 何かが開いたままにしている(ソケットが閉じていない)、または
  2. 関連するパスがあります

いいえfor2。その「関連付けられたパス」を削除(unlink()ed)して、ソケットを別のハードリンクからアクセスできます。

デモと説明については、他の answer を参照してください。

ソケットのiノード(実際のソケットfdによって示され、/proc/PID/fd/FDからもアクセスできるもの)と、バインドされている可能性のあるiノード(/tmp/.X11-unix/X0のようなソケットファイル)を混同しているようです。それらは異なり、後者は「エントリポイント」としてのみ使用されます。バインドされたソケットが閉じられるとすぐに、ソケットファイルはファイルシステム内のダミーのiノードにすぎません。

パスが特殊文字\ 0で始まる場合、ファイルはファイルシステムに表示されません。)

.Sun_path\0で始まる場合、これはパスではなく、「抽象的な」UNIXドメインアドレスです。これは、パスとは異なり、他の\0バイトを含み、セマンティクスがまったく異なります(誰でも接続できます)ソケットへの接続。古いスタイルのUNIXドメインソケットとは異なり、ソケットへの接続は、先頭のパスによって決定されるファイルアクセス許可の対象となります)。

この「抽象ソケット」機能はLinuxにのみ存在することに注意してください。

1
Uncle Billy