可能重复:
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();
}
所以我想我的问题是,这是正确的方法吗?如果是这样,我发送什么信号,我需要定义信号处理程序,还是可以使用信号处理“忽略”并仍然被唤醒?
答案 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();
}