我也建议使用 select 或其他一些非基于信号的方法来终止你的线程。我们拥有线程的原因之一是试图摆脱疯狂的信号。那就是说...
通常使用 pthread_kill() 和 SIGUSR1 或 SIGUSR2 向线程发送信号。其他建议的信号——SIGTERM、SIGINT、SIGKILL——具有您可能不感兴趣的进程范围的语义。
至于你发送信号时的行为,我的猜测是它与你如何处理信号有关。如果您没有安装处理程序,则应用该信号的默认操作,但在接收信号的线程的上下文中。因此,例如,SIGALRM 将由您的线程“处理”,但处理将包括终止进程——可能不是所需的行为。
线程接收到信号通常会将其从使用 EINTR 的读取中中断,除非它确实处于前面答案中提到的那种不间断状态。但我认为不是,否则您对 SIGALRM 和 SIGIO 的实验不会终止该过程。
您的阅读可能处于某种循环中吗?如果读取以 -1 返回终止,则跳出该循环并退出线程。
您可以使用我放在一起的这个非常草率的代码来测试我的假设——我现在离我的 POSIX 书籍有几个时区......
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
int global_gotsig = 0;
void *gotsig(int sig, siginfo_t *info, void *ucontext)
{
global_gotsig++;
return NULL;
}
void *reader(void *arg)
{
char buf[32];
int i;
int hdlsig = (int)arg;
struct sigaction sa;
sa.sa_handler = NULL;
sa.sa_sigaction = gotsig;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
if (sigaction(hdlsig, &sa, NULL) < 0) {
perror("sigaction");
return (void *)-1;
}
i = read(fileno(stdin), buf, 32);
if (i < 0) {
perror("read");
} else {
printf("Read %d bytes\n", i);
}
return (void *)i;
}
main(int argc, char **argv)
{
pthread_t tid1;
void *ret;
int i;
int sig = SIGUSR1;
if (argc == 2) sig = atoi(argv[1]);
printf("Using sig %d\n", sig);
if (pthread_create(&tid1, NULL, reader, (void *)sig)) {
perror("pthread_create");
exit(1);
}
sleep(5);
printf("killing thread\n");
pthread_kill(tid1, sig);
i = pthread_join(tid1, &ret);
if (i < 0)
perror("pthread_join");
else
printf("thread returned %ld\n", (long)ret);
printf("Got sig? %d\n", global_gotsig);
}