【问题标题】:epoll_wait doesn't wake up until pressing on enterepoll_wait 在按下 enter 之前不会唤醒
【发布时间】:2020-04-14 11:58:56
【问题描述】:

我是 epoll 的新手。 我的代码工作正常。 epoll 正在存储我的文件描述符并等待文件描述符“准备好”。 但是,由于某种原因,在我按下 Enter 之前它不会唤醒(即使数据已经接收到 fd,并且在输入后我会立即看到之前发送的所有数据)。 一次输入后,它将按预期工作(无需输入,当 fd 再次准备好时,它会再次唤醒)。

这是我的代码的精髓:

    int nEventCountReady = 0;
    epoll_event event, events[EPOLL_MAX_EVENTS];
    int epoll_fd = epoll_create1(0);

    if(epoll_fd == -1)
    {
        std::cout << "Error: Failed to create EPoll" << std::endl;
        return ;
    }

    event.events = EPOLLIN;
    event.data.fd = myfd;

    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 0, &event))
    {
        fprintf(stderr, "Failed to add file descriptor to epoll\n");
        close(epoll_fd);
        return ;
    }

    while(true)
    {
        std::cout << "Waiting for messages" << std::endl;
        nEventCountReady = epoll_wait(epoll_fd, events, EPOLL_MAX_EVENTS, 30000); << Stuck until Enter will be pressed (at first while loop)
        for(int i=0; i<nEventCountReady; i++)
        {
            msgrcv(events[i].data.fd, oIpCMessageContent, sizeof(SIPCMessageContent), 1, 0);
            std::cout << oIpCMessageContent.buff << std::endl;
        }
    }

【问题讨论】:

  • event.data.fd = myfd; - 什么是myfd?它是如何打开的?
  • 只是一个普通的file-descriptor..更具体地说,fd是msgget的一个文件描述符。
  • 你应该创建一个minimal reproducible example
  • 我不认为msgget 返回文件描述符。从外观上看,我 myfd 等于STDIN_FILENO,而您实际上是在轮询stdin。哪一种可能解释它 - 你轮询 STDIN,阻塞直到你输入一些东西并输入,因为它是行缓冲的,然后你不会从 stsdin 读取任何东西,所以epoll_wait 立即返回。 To be more specific - 请更具体。
  • @KamilCuk msgget 函数的结果不等于 STDIN_FILENO,但我刚刚阅读了有关 msgget 的信息,你对这个函数说它不返回文件描述符,它返回“System V 消息队列标识符" 我认为是一个文件描述符。

标签: c++ epoll


【解决方案1】:

这个

if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 0, &event))

应该是

if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, myfd, &event))

在第一行中,您告诉 epoll 监视 fd 0,它通常是标准输入。这就是它等待它的原因,例如供您输入。

请注意,您的原始代码只是巧合。碰巧的是,当您输入时,您的 myfd 中有数据(即使没有 msgrcv 块)。一旦你按下 Enter 它就会一直唤醒,因为 epoll 知道 STDIN 已准备好但你没有从中读取。

【讨论】:

  • 我以前试过这个,但是当我这样做时,epoll_ctl总是返回-1。所以我虽然这种方式不正确,我应该输入 0。无论如何,它返回 -1 并且 errno 是 9(即 'EBADF')。正如我之前所说,我的 fd 由函数 msgget 生成)。
  • 添加0 让它等待stdin 上的事件,所以这是正确的答案。
  • @YaronIsraeli msgget 不返回文件描述符。 AFAIK System V 消息队列不适用于 epoll 等选择器。
【解决方案2】:

感谢 kamilCuk,我注意到 msgget 并没有像我想象的那样返回文件描述符。 它返回一个“System V 消息队列标识符”。

正如之前所说的,System V 消息队列不适用于 epoll 这样的选择器。

【讨论】:

  • 我建议你接受怪胎的回答,因为它回答了你的问题。
猜你喜欢
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多