【发布时间】:2012-04-30 16:26:00
【问题描述】:
我有一个父进程和一个分叉的子进程,它们共享一个使用socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) 创建的 Unix 域 IPC 套接字。两个进程都关闭套接字对的一端,并将另一端保存到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 的对象
man page for unix domain sockets 只说:
ECONNRESET:远程套接字意外关闭。
但由于 Unix 域套接字是本地 IPC 事物,我想它可能会更具体地说明可能发生此错误的情况。
我的“更深层次的想法”是这样的:如果规范说例如close 只有在没有数据要从套接字读取的情况下才会生成流结束标记,它如何知道其他进程是否只是要写入一些数据?这不会造成竞争条件吗?内核如何知道连接是否会正常关闭?
【问题讨论】:
-
不确定这是否有帮助,但您是否尝试过在
close()之前使用shutdown()? -
我刚刚尝试过,使用
shutdown(); close();的行为相同,但使用shutdown(); sleep(1); close();实际上可以优雅地关闭连接。所以它似乎创造了一个竞争条件,当套接字的另一端“轮到”足够快时,它会没事的。所以这是不需要的,我不能打电话给sleep(...)。
标签: linux sockets unix ipc pipe