【问题标题】:File decriptors and socket connections文件描述符和套接字连接
【发布时间】: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


【解决方案1】:

您的额外文件描述符很可能与syslog 有关。 Syslog 必须打开一个到 syslogd 的套接字来报告消息。除非您明确调用openlog,否则此套接字在第一次调用syslog 时打开,并且由于您在出现错误之前不会调用syslog,您很可能会观察到syslog 的副作用。

【讨论】:

  • 正是问题所在。谢谢 ! :))
  • 另外:有一个对 openlog 的显式调用,但套接字出现在第一个 syslog 调用之后。
【解决方案2】:

调试此类问题的最简单方法是在strace(1) 实用程序下运行您的应用程序。检查进行了哪些系统调用,参数和返回值是什么,并将其与使用的文件描述符相关联。

【讨论】:

    【解决方案3】:

    请提供更多代码。

    但我猜您正在查看套接字的操作系统实现。
    它可能使用一个文件描述符来读取和另一个用于写入(但这是一个猜测)。

    操作系统在/proc/pid 中所做的事情对您有什么影响?里面的东西并不是供您直接使用的。

    【讨论】:

      【解决方案4】:

      你是对的,它是两个。你一定把第三个和别的东西混淆了。

      没有更多信息很难提供帮助。

      【讨论】:

        猜你喜欢
        • 2012-11-02
        • 1970-01-01
        • 2014-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多