我被这个模拟服务器 - 客户端交互的代码片段所困扰,假设 sockfd 是在服务器端创建的套接字文件描述符。
我的问题是当父和它的子进程'同时'运行时,并且在子进程执行时间片期间,它关闭服务器套接字 sockfd ,然后当执行流到,例如,第二次循环,调用accpet函数,参数 sockfd 有效,它是否由子进程关闭,即从内核文件描述符表中解除分配?
while (1) {
//accept a connection from client,get the new socket from client
//is the sockfd valid here,is it closed by the child in
//the previous loop
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
if (pid < 0)
error("ERROR on fork");
if (pid == 0) {
close(sockfd); // can't this cause problem ??
dostuff(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
答案 0 :(得分:6)
在这段代码中:
if (pid == 0) {
close(sockfd); // can't this cause problem ??
dostuff(newsockfd);
exit(0);
}
close()
仅影响子文件sockfd
文件描述符的副本。
父母的副本仍然在下次循环播放时使用。
子进程被认为是关闭不需要的继承文件描述符的良好方式。
答案 1 :(得分:0)
父级所做的任何事都不会导致子文件描述符在你的意思上被关闭。对其的操作将根据具体情况返回适当的状态,但在{2}或open
之前,该子编号永远不会返回该子编号,直到子进程调用dup
。
答案 2 :(得分:0)
每当您调用fork()
函数时,子进程都会复制当前进程。因此,在第二个循环中,子进程中的sockfd
与父进程(尚未关闭)相同。所以这是有效的。
答案 3 :(得分:0)
当你关闭重复的fd时,它似乎并没有真正关闭流,直到所有关闭。我使用我创建的一个有趣的网络服务器遇到了这个问题。我在叉子上关闭了fd,但它仍保持打开状态。
我通过在fork之后关闭它来修复它。