3

親プロセスと分岐した子プロセスがあり、これらは で作成された Unix ドメイン IPC ソケットを共有していますsocketpair(AF_UNIX, SOCK_STREAM, 0, sockets)。両方のプロセスがソケット ペアの一方の端を閉じ、もう一方の端をsock変数に保存します。その後、彼らはこれを行います:

int sock; // Unix-domain socket

void child_main()
{
  printf("I am child\n");      
  sleep(1);      
  close(sock);
}

void parent_main()
{
  printf("I am parent\n");

  write(sock, "hello", 5);

  char buf[100];
  int ret = read(sock, buf, 100); // this read will return ECONNRESET
  if (ret == -1) { 
    perror("read");
    exit(-1);
  }
}

親プロセスはソケットにデータを書き込みますが、子プロセスはそれを読み取りません。代わりに、子はソケットを閉じます。今私の懸念はread、親プロセスでECONNRESET(ピアによる接続リセット)で失敗することですが、ストリームの終わりを示す「0」が返されることを期待しています。ソケットのもう一方の端は、を呼び出すことによって正常に閉じられたためcloseです。

今、私はその動作 (保留中のデータを読み取らずにソケットを閉じると ECONNRESET が生成される) を理解していますが、これはどこに文書化されていますか? man readECONNRESET については何も述べていませんが、次のように言及しています。

fd に接続されたオブジェクトによっては、その他のエラーが発生する場合があります。

UNIXドメインソケットのmanページには、次のように書かれています:

ECONNRESET: リモート ソケットが予期せず閉じられました。

しかし、Unix ドメイン ソケットはローカルの IPC であるため、このエラーが発生する可能性がある状況については、より具体的に説明できると思います。

私の「より深い考え」は次のようなものです:仕様が、たとえばclose、ソケットから読み取るデータがない場合にのみストリームの終わりマークを生成すると言う場合、他のプロセスがちょうど書き込みしようとしていないかどうかをどのように知るのですか?いくつか?それは競合状態を作成しませんか?カーネルは、接続が正常に閉じられるかどうかをどのように認識しますか?

4

1 に答える 1

2

ステートフル ソケット (unix ドメインまたは tcp) では、「利用可能なデータがない」ことと相手側のソケットのクローズを区別する最善の方法は、最初に select() を使用し、readfds を渡すことです (man 2 select を参照)。選択が読み取りイベントを示している場合にのみ、ソケットで read() を試みます。読み取られたバイト数が 0 の場合は、ソケットが閉じられたことを意味します (ピアによって接続がリセットされました)。

于 2012-04-30T16:37:17.100 に答える