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 read对 ECONNRESET 只字未提,但它提到:

可能会出现其他错误,具体取决于连接到 fd 的对象

unix 域套接字的手册页只说:

ECONNRESET:远程套接字意外关闭。

但是由于 Unix 域套接字是本地 IPC 的东西,我想它可能更具体地说明可能发生此错误的情况。

我的“更深层次的想法”是这样的:如果规范说 egclose只有在没有数据要从套接字读取的情况下才会生成流结束标记,它如何​​知道其他进程是否不只是要写入一些?这不会造成竞争条件吗?内核如何知道连接是否会正常关闭?

4

1 回答 1

2

对于有状态套接字(unix 域或 tcp),区分“无可用数据”和另一端套接字关闭的最佳方法是首先使用 select(),传递一个 readfds(参见 man 2 select)。当且仅当 select 指示读取事件时,才尝试在套接字上执行 read()。如果读取的字节数为 0,则表示套接字已关闭(对等方重置连接)。

于 2012-04-30T16:37:17.100 回答