C++ 如何检测其他程序关闭的eventfd文件描述符

C++ 如何检测其他程序关闭的eventfd文件描述符,c++,linux,C++,Linux,我有一个客户机/服务器通过eventfd进行通信。如果客户端或服务器调用close(fd)我想让另一端知道(比如现在关闭了文件描述符)。我尝试使用非零超时的select,它总是返回0,这是超时。我看到有人建议使用fcntl它似乎也不起作用。有什么建议吗 添加详细信息(省略非重要部件代码,您可以看到: 它是多进程应用程序。服务器进程通过调用 struct msghdr control_message; int fd = eventfd(0,0); *CMSG_DATA(control_mes

我有一个客户机/服务器通过eventfd进行通信。如果客户端或服务器调用
close(fd)
我想让另一端知道(比如现在关闭了文件描述符)。我尝试使用非零超时的
select
,它总是返回0,这是超时。我看到有人建议使用
fcntl
它似乎也不起作用。有什么建议吗

添加详细信息(省略非重要部件代码,您可以看到: 它是多进程应用程序。服务器进程通过调用

 struct msghdr control_message;
 int fd = eventfd(0,0);
 *CMSG_DATA(control_message) = fd;
 message.msg_control = &control_message;
 sendmsg(socket_fd, & message,0); //send this to client
从客户端:

 recvmsg(socket_fd, & message,0);
 //loop using CMSG_NXTHDR(&message, control_message)
 int fd = *(int *) CMSG_DATA(contro_message);
然后在服务器端:

 close(fd);
在客户端: int rc; rc=dup2(fd,fd)


rc从来都不是无效的。

检查关闭的文件描述符?这个怎么样

#include <errno.h>
#include <stdio.h>
#include <string.h>

static void checkit ()
{
    int     rc;

    rc = dup2(2, 2);

    if ( rc == -1 )
            printf("error %d on dup2(2, 2): %s\n", errno, strerror(errno));
    else
            printf("dup2 successful\n");

    write(2, "still working\n", 14);
}

int main (int argc, char **argv)
{
    int     rc;

    checkit();

    close(2);

    checkit();

    return  0;
}
如果这是一个使用poll的多线程应用程序,并且您希望poll在另一个线程关闭文件描述符时返回,则POLLERR、POLLHUP或POLLNVAL可能会有所帮助

使用轮询的多线程版本

下面的示例演示了如何在多线程程序中通过poll(POLLNVAL是事件)检测关闭的fd:

#include <errno.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static void *run_poll (void *arg)
{
    struct pollfd   fds[1];
    int             rc;

    fds[0].fd = 2;
    fds[0].events = POLLERR | POLLHUP | POLLNVAL;

            //
            // Poll indefinitely
            //

    printf("starting poll\n");
    fflush(stdout);
    rc = poll((struct pollfd *) &fds, 1, -1);

    if ( rc == -1 )
    {
            printf("POLL returned error %d: %s\n", errno, strerror(errno));
    }
    else
    {
            printf("POLL returned %d (revents = 0x%08x): %s %s %s\n",
                   rc,
                   fds[0].revents,
                   ( ( fds[0].revents & POLLERR  ) ? "pollerr" : "noerr" ),
                   ( ( fds[0].revents & POLLHUP  ) ? "pollhup" : "nohup" ),
                   ( ( fds[0].revents & POLLNVAL ) ? "pollnval" : "nonval" ));
    }

    return  NULL;
}

int main (int argc, char **argv)
{
    pthread_t       thread;
    int             rc;

    rc = pthread_create(&thread, NULL, run_poll, NULL);

    usleep(100);
    printf("closing stderr\n");
    close(2);
    usleep(100);

    return  0;
}

顺便说一句,errno EBADF是“错误的文件描述符”。您使用了一个众所周知的fd(stderr)。我使用了由
eventfd(0,0)
返回的fd。我还有两个进程代替了多线程。我发现,在服务器中打开的文件描述符传递给客户端时变为有效(即使数值相同).我使用了dup2技巧,它返回负值(错误号9,文件描述符无效)。这是正确的-文件描述符是特定于打开它们的进程的。事实上,0、1和2始终是进程的stdin、stdout和stderr-因此您可以看到它们如何不容易共享。通常不可能在一个进程中打开一个文件并在另一个进程中访问它。您能解释一下用例吗?我可能可以帮助解决问题。我刚刚更新了我的问题,因为在问题中设置格式比在评论中设置格式更容易。你能检查一下吗?谢谢。
#include <errno.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static void *run_poll (void *arg)
{
    struct pollfd   fds[1];
    int             rc;

    fds[0].fd = 2;
    fds[0].events = POLLERR | POLLHUP | POLLNVAL;

            //
            // Poll indefinitely
            //

    printf("starting poll\n");
    fflush(stdout);
    rc = poll((struct pollfd *) &fds, 1, -1);

    if ( rc == -1 )
    {
            printf("POLL returned error %d: %s\n", errno, strerror(errno));
    }
    else
    {
            printf("POLL returned %d (revents = 0x%08x): %s %s %s\n",
                   rc,
                   fds[0].revents,
                   ( ( fds[0].revents & POLLERR  ) ? "pollerr" : "noerr" ),
                   ( ( fds[0].revents & POLLHUP  ) ? "pollhup" : "nohup" ),
                   ( ( fds[0].revents & POLLNVAL ) ? "pollnval" : "nonval" ));
    }

    return  NULL;
}

int main (int argc, char **argv)
{
    pthread_t       thread;
    int             rc;

    rc = pthread_create(&thread, NULL, run_poll, NULL);

    usleep(100);
    printf("closing stderr\n");
    close(2);
    usleep(100);

    return  0;
}
starting poll
closing stderr
POLL returned 1 (revents = 0x00000020): noerr nohup pollnval