Linuxはアプリケーションの終了時にソケットを閉じることをいつ/どのように決定しますか?

Linuxはアプリケーションの終了時にソケットを閉じることをいつ/どのように決定しますか?

同じLinuxシステムで実行されるサーバープロセスとクライアントプロセスがあります。

場合によってkill -9は、クライアントの場合にメッセージが送信されるのがわかりtcpdumpますFIN, ACK。もちろん死んだ依頼人は残酷に死んだからこういうことはできないだろうSIGKILL。だから、Linux OSが接続の終了を処理していると思います。

場合によっては、接続の終了処理が表示されず、接続が「設定済み」のままになることがあります(netstat)。

接続がまだ閉じていることがわかりますLinux ubuntu 4.4.0-53-generic
時々Linux 3.13.11(Ubuntuではなく純粋なカーネル)で接続が閉じていることがわかります。

私の質問は次のとおりです

  1. Linuxは接続の終了を処理しますか?
    1.1どこSIGKILL
    1.2.アプリケーションが正しく終了したが呼び出されない場合close()
  2. カーネルバージョン間でこの機能は変わりますか3.13.114.4.0Ubuntuに関連するものはありますか?
  3. 両方のプロセスが同じLinuxシステムにない場合はどうなりますか?同じように動作しますか?
  4. 接続が時々「設定された」状態に保たれるのはなぜですか?
  5. keepaliveTCPソケットオプションについて知っています。 Linuxが実際に接続終了を処理する場合。なぜ存在するのですか?FIN, ACKパケットが失われた場合にのみ?

答え1

広範な質問です。たぶん、誰かが特定のカーネルバージョン間のカーネルTCPスタックに関するあなたの質問に重みを置くことができます。

いくつかの一般的な答え:

クライアントから

  1. シグナルが発生すると、SIGKILLカーネルはプログラムの実行を終了し、プロセスのオープンファイル記述子を閉じます。カーネルはTCPソケットをフラッシュし、TCPシャットダウンプロセスを経なければならないという点で、通常のファイルとは少し異なるようにTCPソケットを処理します。

    クライアントの即時の「FIN、ACK」と長いソケットのクローズの違いは、クライアントアプリケーションがシャットダウンしたときのクライアントTCP接続の状態によって異なります。しかし、通常、カーネルはアプリケーションが開いたソケットを閉じます。

サーバー側から

  1. サーバーは、クライアント接続がいつ切断されるかを常に知ることはできません。クライアントがハングしていることを確認する最も信頼性の高い方法は、EOFを返すソケットから読み取りを試みることです。

    TCPは、接続遅延と断続的なエラーに耐えるように設計されています。これはまた、FIN, ACK4方向の切断ハンドシェイクが発生せず、切断を確実に検出するためにいくつかの問題があることを意味します。

一般化する

kill -9クライアント側では、サーバーがCLOSE_WAITTCP状態に入り、TCPタイムアウトを待っていることがわかります。時間がかかる場合があります。クライアントが消えてもカーネルがTCP切断ハンドシェイクを処理しない場合、サーバーはタイムアウトする必要があります。

ESTABLISHED私の記憶には、これには数秒かかることがあり、同じホスト上でクライアントとサーバーを実行しているため、このメッセージが引き続き表示される理由かもしれません。

関連情報