如何用适当的信号中断epoll_pwait?

时间:2012-01-27 04:18:41

标签: c linux

  

可能重复:
  Interrupting epoll_wait with a non-IO event, no signals

我有一个线程,当前正在使用epoll_wait来标记某些套接字上的数据到达。 timeout参数当前设置为零。

但是,该线程还执行其他任务。我想要做的就是改变它,这样如果没有工作要做,那就让它无限期或长时间用完。当没有实际工作时,这将大大减少浪费的CPU周期。

整个事情主要是由消息到达线程安全锁定空闲队列。

所以,我认为应该发生的是我应该使用epoll_pwait唤醒线程长时间的超时。

但是,我不确定发送它的信号以及如何完成。我不熟悉Linux信号。

以下与我目前的相似。显着缩短以显示概念。如果您发现了一个错误,请不要指出它,这只是我在这里输入的一个插图,以帮助您理解我想要实现的目标。

// Called from another thread...
void add_message_to_queue(struct message_t* msg)
{
    add_msg(msg);
    raise( ? );  // wake the state machine?
}


// different thread to the above.
main_thread()
{
    struct message_t msg;
    while (msg = get_message_from_queue())
      process_message(msg);

    timeout = work_available ? 0 : -1;

    nfds = epoll_pwait(epfd, events, MAX_EPOLL_EVENTS, timeout);
    for (i = 0; i < nfds; ++i)
    {
        if ((events[i].events & EPOLLIN) == EPOLLIN)
        {
           /// do stuff
        }
    }

    run_state_machines();
}

所以我想我的问题是,这是正确的方法吗?如果是这样,我发送什么信号,我需要定义信号处理程序,还是可以使用信号处理“忽略”并仍然被唤醒?

1 个答案:

答案 0 :(得分:2)

考虑使用pipe而不是信号。创建管道并将管道读取端的文件描述符添加到epoll。如果要唤醒epoll_wait调用,只需将1个字符写入管道的写入端。

int read_pipe;
int write_pipe;
void InitPipe()
{
    int pipefds[2] = {};
    epoll_event ev = {};
    pipe(pipefds, 0);
    read_pipe = pipefds[0];
    write_pipe = pipefds[1];

    // make read-end non-blocking
    int flags = fcntl(read_pipe, F_GETFL, 0);
    fcntl(write_pipe, F_SETFL, flags|O_NONBLOCK);

    // add the read end to the epoll
    ev.events = EPOLLIN;
    ev.data.fd = read_pipe;
    epoll_ctl(epfd, EPOLL_CTL_ADD, read_pipe, &ev);

}

void add_message_to_queue(struct message_t* msg)
{
    char ch = 'x';
    add_msg(msg);
    write(write_pipe, &ch, 1);
}

main_thread()
{
    struct message_t msg;
    while (msg = get_message_from_queue())
      process_message(msg);

    timeout = work_available ? 0 : -1;

    nfds = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, timeout);

    for (i = 0; i < nfds; ++i)
    {
        if (events[i].data.fd == read_pipe)
        {

            // read all bytes from read end of pipe
            char ch;
            int result = 1;
            while (result > 0)
            {
                result = read(epoll_read, &ch, 1);
            }
        }

        if ((events[i].events & EPOLLIN) == EPOLLIN)
        {
           /// do stuff
        }
    }

    run_state_machines();
}