我试图了解文件描述符与套接字的关系。根据我的理解,你监听一个特定的文件描述符,一旦连接进来,你接受它,它返回另一个文件描述符(总共2个),你使用这个第二个描述符发送/ recv数据。
我观察到的奇怪行为是,在接受之后,我有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并且在接受之后,fd变为3.操作系统是Fedora核心13。
我需要验证这一点的原因是我不希望我的进程持有FD的;由于随着时间的推移成为守护进程,它可能会将系统带入一个角落......
这似乎很奇怪。在关闭接受的连接后,我仍然留下了两个fd。 即一个用于监听和一个鬼fd ......更奇怪的是,即使建立了10个连接,只有一个鬼fd在所有关闭结束时仍然存在....
听起来像操作系统特定的实现..
干杯!
答案 0 :(得分:2)
您的额外文件描述符很可能与syslog
相关。 Syslog必须打开syslogd的套接字来报告消息。除非您明确调用openlog
,否则在第一次调用syslog
时会打开此套接字,并且由于在出现错误之前未调用syslog
,因此您很可能会观察syslog
的副作用。
答案 1 :(得分:1)
调试此类问题的最简单方法是在strace(1)
实用程序下运行您的应用。检查进行了哪些系统调用,参数和返回值是什么,并将其与使用的文件描述符相关联。
答案 2 :(得分:0)
请更多代码。
但我猜你正在考虑套接字的操作系统实现 它可能使用一个文件描述符进行读取而另一个用于写入(但这是猜测)。
操作系统在/proc/pid
中所做的事情对您来说有什么关系。那里的内容并不适合您直接使用。
答案 3 :(得分:0)
你是对的,因为它是两个。你必须把第三个与其他东西混淆。
没有更多信息,很难提供帮助。