gpt4 book ai didi

c - 谁是第 4 个线程,同时使用 3 个线程进行信号处理

转载 作者:太空宇宙 更新时间:2023-11-04 03:11:30 25 4
gpt4 key购买 nike

我正在体验信号的 react ,与线程一起使用。我知道 printf 系列函数不是信号安全函数,但为了简单起见,我使用了它。下面说说

When a signal is delivered to a multithreaded process that has established a signal handler, the kernel arbitrarily selects one thread in the process to which to deliver the signal and invokes the handler in that thread. This behavior is cosistent with maintaining the traditional signal semantics. It would not make sense for a process to perform the signal handling actions multiple times in response to a single signal.

为了体验粗体文本,我编写了以下基本代码,但是当我按下 Ctrl-C 时,我得到了一个完全不同的线程 ID,而不是创建的线程 ID。这是谁?为什么我看不到另一个线程可以捕获信号。

#include <pthread.h>
#include <stdio.h>
#include <signal.h>

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;

int count = 0;
int globerr;

void *inc(void *arg) {
fprintf(stderr, "Thread id = %d\n", (int)pthread_self());
sleep(2);
int error;
for (int i = 0; i < 15; ++i) {
if (error = pthread_mutex_lock(&mtx)) {
globerr = error;
return 0;
}

count++;
printf("thread id = %d, count = %d\n", pthread_self(), count);
if (count == 20) {

printf("thread id = %d, SIGNAL count = %d\n", pthread_self(), count);
pthread_cond_signal(&cv);
}


if (error = pthread_mutex_unlock(&mtx)) {
globerr = error;
return 0;
}
}
}

void* watcher(void *arg) {
fprintf(stderr, "Thread id = %d\n", (int)pthread_self());
sleep(2);
int error;
if (error = pthread_mutex_lock(&mtx)) {
globerr = error;
return 0;
}

while (count < 20) {
printf("watcher thread id = %d, BLOCKING count = %d\n", pthread_self(), count);
pthread_cond_wait(&cv, &mtx);
printf("watcher thread id = %d, UNBLOCKING count = %d\n", pthread_self(), count);

}


printf("watcher thread id = %d, count = %d\n", pthread_self(), count);

if (error = pthread_mutex_unlock(&mtx)) {
globerr = error;
return 0;
}

}

static void signal_handler(int sig){
if (sig == SIGINT)
printf("Caught signal for Ctrl+C, Thread id = %d\n", (int)pthread_self());

pthread_cancel(pthread_self());
}

int main(void) {
struct sigaction sigact;
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, (struct sigaction *)NULL);

pthread_t t[3];
for (int i = 0; i < 2; ++i) {
pthread_create(&t[i], 0, inc, 0);
}

pthread_create(&t[2], 0, watcher, 0);

sleep(3);

for (int i = 0; i < 3; ++i) {
pthread_join(t[i], 0);
}
}

示例输出,

MacBook-Pro-2:cmake-build-debug soner$ ./client 
Thread id = 171921408
Thread id = 172457984
Thread id = 172994560
^CCaught signal for Ctrl+C, Thread id = 360719808
^CCaught signal for Ctrl+C, Thread id = 171921408
^CCaught signal for Ctrl+C, Thread id = 172457984
^CCaught signal for Ctrl+C, Thread id = 172994560

360719808 是谁?

最佳答案

如果调用 pthread_create 三次,则您的程序有四个线程:第四个是初始线程,它从程序一开始就存在。您可以将其视为线程过程为 main 的线程。

在这样的程序中,您应该将一个线程专用于信号处理。您可以通过四个步骤完成此操作:

  1. main 中,在创建任何线程之前,使用 pthread_sigmask 阻止所有信号,除了指示同步致命事件的信号(SIGABRT、SIGBUS 、SIGFPE、SIGILL、SIGSEGV、SIGSYS 和 SIGTRAP)。不要安装任何信号处理程序。
  2. 使用专用于信号处理的线程过程创建一个线程。
  3. 该线程循环调用 sigwaitinfo 以获取您关心的信号。这必须至少包括指示外部终止或暂停请求的信号:SIGINT、SIGHUP、SIGPWR、SIGQUIT、SIGTERM、SIGTSTP、SIGXCPU。如果您使用子进程,您还必须包含 SIGCHLD。
  4. 你的其他线程做他们需要做的任何事情而不用担心信号。他们可能大部分时间都花在计算上或忙于select

关于c - 谁是第 4 个线程,同时使用 3 个线程进行信号处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55951924/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com