等待时中断 pselect - 多线程
Interrupting pselect when it's waiting - multithread
因此,根据手册,pselect
可以有一个超时参数,如果没有文件描述符发生变化,它将等待。此外,它还有一个被信号中断的选项:
sigemptyset(&emptyset); /* Signal mask to use during pselect() */
res = pselect(0, NULL, NULL, NULL, NULL, &emptyset);
if (errno == EINTR) printf("Interrupted by signal\n");
但是从手册上看并不明显哪些信号能够中断 pselect?
如果我有线程(生产者和消费者),并且每个(消费者)线程都在使用 pselect,有没有办法从另一个(生产者)线程中断一个(消费者)线程?
我认为问题在https://lwn.net/Articles/176911/
中得到了分析
For this reason, the POSIX.1g committee devised an enhanced version of
select()
, called pselect()
. The major difference between select()
and
pselect()
is that the latter call has a signal mask (sigset_t)
as an
additional argument:
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
const struct timespec *timeout, const sigset_t *sigmask);
pselect
使用 sigmask
参数来配置哪些信号可以中断它
The collection of signals that are currently blocked is called the
signal mask. Each process has its own signal mask. When you create a
new process (see Creating a Process), it inherits its parent’s mask.
You can block or unblock signals with total flexibility by modifying
the signal mask.
来源:https://www.gnu.org/software/libc/manual/html_node/Process-Signal-Mask.html
https://linux.die.net/man/2/pselect
https://www.linuxprogrammingblog.com/code-examples/using-pselect-to-avoid-a-signal-race
由于您的第二个问题,进程同步有多种算法,请参见 https://www.geeksforgeeks.org/introduction-of-process-synchronization/ and the links down on this page or https://en.wikipedia.org/wiki/Sleeping_barber_problem and associated pages. So basically signals are only one path for IPC in linux, cf IPC using Signals on linux
(忽略问题的所有信号部分,只回答
If I have threads (producers and consumers), and each (consumer)thread
is using pselect, is there a way to interrupt only one
(consumer)thread from another(producer) thread?"
,因为标题并不暗示信号的使用)。
我知道的最简单的方法是让线程公开一个文件描述符,该文件描述符将始终包含在 p/select 受监视的描述符中,因此它始终至少监视一个。如果其他线程写入,p/select 调用将 return:
struct thread {
pthread_t tid;
int wake;
...
}
void *thread_cb(void *t) {
struct thread *me = t;
t->wake = eventfd(0, 0);
...
fd_set readfds;
// Populate readfds;
FD_SET(t->wake, &readfds);
select(...);
}
void interrupt_thread(struct thread *t) {
eventfd_write(t->wake, 1);
}
如果没有可用的 eventfd,您可以将其替换为经典(且更冗长)的管道或其他类似的通信机制。
因此,根据手册,pselect
可以有一个超时参数,如果没有文件描述符发生变化,它将等待。此外,它还有一个被信号中断的选项:
sigemptyset(&emptyset); /* Signal mask to use during pselect() */
res = pselect(0, NULL, NULL, NULL, NULL, &emptyset);
if (errno == EINTR) printf("Interrupted by signal\n");
但是从手册上看并不明显哪些信号能够中断 pselect?
如果我有线程(生产者和消费者),并且每个(消费者)线程都在使用 pselect,有没有办法从另一个(生产者)线程中断一个(消费者)线程?
我认为问题在https://lwn.net/Articles/176911/
中得到了分析For this reason, the POSIX.1g committee devised an enhanced version of
select()
, calledpselect()
. The major difference betweenselect()
andpselect()
is that the latter call has a signal mask(sigset_t)
as an additional argument:
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);
pselect
使用 sigmask
参数来配置哪些信号可以中断它
The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.
来源:https://www.gnu.org/software/libc/manual/html_node/Process-Signal-Mask.html
https://linux.die.net/man/2/pselect
https://www.linuxprogrammingblog.com/code-examples/using-pselect-to-avoid-a-signal-race
由于您的第二个问题,进程同步有多种算法,请参见 https://www.geeksforgeeks.org/introduction-of-process-synchronization/ and the links down on this page or https://en.wikipedia.org/wiki/Sleeping_barber_problem and associated pages. So basically signals are only one path for IPC in linux, cf IPC using Signals on linux
(忽略问题的所有信号部分,只回答
If I have threads (producers and consumers), and each (consumer)thread is using pselect, is there a way to interrupt only one (consumer)thread from another(producer) thread?"
,因为标题并不暗示信号的使用)。
我知道的最简单的方法是让线程公开一个文件描述符,该文件描述符将始终包含在 p/select 受监视的描述符中,因此它始终至少监视一个。如果其他线程写入,p/select 调用将 return:
struct thread {
pthread_t tid;
int wake;
...
}
void *thread_cb(void *t) {
struct thread *me = t;
t->wake = eventfd(0, 0);
...
fd_set readfds;
// Populate readfds;
FD_SET(t->wake, &readfds);
select(...);
}
void interrupt_thread(struct thread *t) {
eventfd_write(t->wake, 1);
}
如果没有可用的 eventfd,您可以将其替换为经典(且更冗长)的管道或其他类似的通信机制。