Linux用のUnixドメインソケットサーバーを書いています。
私がすぐに気付いたUnixドメインソケットの特徴は、リスニングUnixソケットを作成すると、一致するファイルシステムエントリが作成されますが、ソケットを閉じても削除されないことです。さらに、ファイルシステムエントリが手動で削除されるbind()
まで、同じパスに再度ソケットすることはできません。指定されたパスがファイルシステムにすでに存在する場合はbind()
失敗します。EADDRINUSE
結果として、サーバーの再起動unlink()
を回避するために、サーバーのシャットダウン時にソケットのファイルシステムエントリを'edする必要がありEADDRINUSE
ます。ただし、これは常に実行できるとは限りません(つまり、サーバーのクラッシュ)。私が見つけたほとんどのFAQ、フォーラムの投稿、Q&A Webサイトは、回避策として、unlink()
を呼び出す前にソケットにアドバイスするだけbind()
です。ただし、この場合、プロセスを実行する前に、プロセスがこのソケットにバインドされているかどうかを知ることが望ましくなりますunlink()
。
実際、unlink()
プロセスがまだバインドされている間にUnixソケットを作成してから、リスニングソケットを再作成しても、エラーは発生しません。ただし、その結果、古いサーバープロセスはまだ実行されていますが、到達できません。古いリスニングソケットは、新しいリッスンソケットによって「マスク」されます。この動作は避ける必要があります。
理想的には、Unixドメインソケットを使用して、ソケットAPIは、TCPまたはUDPソケットをバインドするときに公開されるのと同じ「相互排除」動作を公開する必要があります。「ソケットSをアドレスAにバインドしたい。プロセスがすでにこのアドレスにバインドされている場合、ただ文句を言う! "残念ながらこれはそうではありません...
この「相互排除」動作を強制する方法はありますか?または、ファイルシステムパスが与えられた場合、ソケットAPIを介して、システム上のプロセスにこのパスにバインドされたUnixドメインソケットがあるかどうかを知る方法はありますか?ソケットAPIの外部で同期プリミティブを使用する必要がありますか(flock()
、...)?それとも私は何かが足りないのですか?
あなたの提案をありがとう。
注:Linuxの抽象名前空間Unixソケットは、へのファイルシステムエントリがないため、この問題を解決しているようですunlink()
。ただし、私が作成しているサーバーは汎用を目的としています。リスニングアドレスの選択については責任を負わないため、両方のタイプのUnixドメインソケットに対して堅牢である必要があります。