【发布时间】:2011-03-31 13:49:52
【问题描述】:
我试图了解文件描述符与套接字的关系。根据我的理解,你监听一个特定的文件描述符,一旦连接进来,你接受它,它会返回另一个文件描述符(总共 2 个),然后你使用这个第二个描述符来发送/接收数据。
我观察到的奇怪行为是,在接受之后,我有 3 个文件描述符而不是两个....我不知道为什么会这样....
我正在使用 lsof 或 /proc/pid 来观察 fd 数量的增加。
ps:这些是 af_unix 套接字。
编辑:代码
这是创建 scoket 的代码。
int s, s2, len;
socklen_t t;
struct sockaddr_un local, remote;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
{
syslog(LOG_ERR,"Failed to create a socket");
exit(1);
}
int flags = fcntl(s, F_GETFD);
if (flags == -1)
{
syslog(LOG_ERR,"Failed to get socket flags");
exit(1);
}
flags |= FD_CLOEXEC;
if (fcntl(s, F_SETFD, flags) == -1)
{
syslog(LOG_ERR,"Failed to set socket flags");
exit(1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH.c_str());
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1)
{
syslog(LOG_ERR,"Failed to bind socket");
exit(1);
}
if (listen(s, 5) == -1)
{
syslog(LOG_ERR,"Failed to listen at socket");
exit(1);
}
接受连接的代码
while (1) { stat =0; execReturn=0; t = len; read_fds = master; if (select(fdmax+1, &read_fds, NULL, NULL, &tv) != -1) { if(FD_ISSET(s,&read_fds)) { //Accept new connection //fork child -> fork grand child //child will return value back if ((s2 = accept(s, (struct sockaddr*)&remote, &t)) == -1) { syslog(LOG_ERR,"Failed to acceptconnection at socket"); exit(1); }
我正在逐步检查 gdb,并且在 accept 之后,fd 变成了 3。操作系统是 fedora core 13。
我需要验证这一点的原因是我不希望我的流程保留 FD 的;由于随着时间的推移成为守护进程,它可能会使系统陷入困境......
这确实看起来很奇怪。关闭接受的连接后,我还剩下两个 fd。 即一个监听一个ghost fd...更奇怪的是,即使建立了10个连接,在所有连接结束时也只剩下一个ghost fd ....
听起来确实像操作系统特定的实现..
干杯!
【问题讨论】:
-
您是否有一小段代码可以重现此问题?
-
很难说没有更多代码和您报告的症状的证据。 (您在接受后立即进行 syslog 吗?那会烧掉 fd。)但是,
lsof和/proc/$pid/fd应该让您确定意外的 fd 是否是绑定或接受的套接字的副本... -
听起来 gdb 正在做某事。
标签: c++ c sockets unix network-programming