Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么主线程被杀死后子线程仍然活着?_C_Linux_Multithreading_Pthreads_Signals - Fatal编程技术网

C 为什么主线程被杀死后子线程仍然活着?

C 为什么主线程被杀死后子线程仍然活着?,c,linux,multithreading,pthreads,signals,C,Linux,Multithreading,Pthreads,Signals,我已经编写了一段代码,其中我从父线程创建了两个子线程 然后,从这些子线程内的另一个终端接收到信号后,我打印threadID,并退出线程 我有两个问题 我正在接收来自子线程的信号。为什么要打印父线程的threadID 杀死父线程后,子线程如何能够存活 守则: void sig_handler(int signo) { if (signo == 1){ printf("%d\n", pthread_self()); pthread_exit(NULL);

我已经编写了一段代码,其中我从父线程创建了两个子线程

然后,从这些子线程内的另一个终端接收到信号后,我打印
threadID
,并退出线程

我有两个问题

  • 我正在接收来自子线程的信号。为什么要打印父线程的
    threadID

  • 杀死父线程后,子线程如何能够存活

  • 守则:

    void sig_handler(int signo)
    {
        if (signo == 1){
            printf("%d\n", pthread_self());
            pthread_exit(NULL);
        }
    }
    
    void* doSomeThing(void* arg)
    {
        printf("In function -> %d\n", pthread_self());
        if (signal(1, sig_handler) == SIG_ERR)
            printf("\ncan't catch SIGHUP\n");
        while(1)
            sleep(1);
        return NULL;
    }
    
    int main(int argc, char *argv[])
    {
        printf("In function -> %d\n", pthread_self());
        char *ch1;
        pthread_t tid1, tid2;
        ch1 = "random";
        int ret1, ret2;
    
        ret1 = pthread_create(&tid1, NULL, &doSomeThing, (void *) ch1 );
        ret2 = pthread_create(&tid2, NULL, &doSomeThing, (void *) ch1 );
    
        while(1)
            sleep(1);
        return 0;
    }
    
    以下是终端中给出的输出图像:

    前3行是3
    threadID
    s。第一个是主
    threadID
    s,然后是两个次线程

    然后从以下代码块打印
    threadID
    s

    if (signo == 1){
        printf("%d\n", pthread_self());
        pthread_exit(NULL);
    }
    

    为什么会发生这种情况?

    信号被传递到进程,而不是单个线程。因此,您不能像这里所做的那样为一个线程使用一个信号处理程序。
    您可以做的是阻止您感兴趣的信号并让专用线程处理使用的信号,这是最常见的方法。

    此外,您只能从信号处理程序中安全地调用异步信号安全函数。发件人:

    异步信号安全功能

    信号处理函数必须非常小心,因为 在执行过程中的某个任意点,其他位置可能会被中断 是节目的一部分。POSIX具有“安全功能”的概念。如果 信号中断不安全函数的执行,处理程序 调用不安全函数或处理程序通过调用
    longjmp()
    siglongjmp()
    程序随后调用 不安全函数,则程序的行为未定义

    链接的手册页有一个函数列表,可以从信号处理程序中安全调用这些函数。如果该函数不在该列表中,则调用它是不安全的。没有例外

    请注意,异步信号安全函数列表中既没有
    printf()
    也没有
    pthread_exit()

    从信号处理程序中调用
    pthread\u exit()
    会产生其他几个问题:

    • 退出的线程通常不受任何控制。在许多情况下,信号可以传送到任何线程

    • 退出的线程可能使对象处于未知状态—例如,互斥锁可能被不再存在的线程锁定

    • 任何线程清理处理程序也将从信号处理程序上下文中调用


    信号
    实际上不适用于线程。这是否意味着
    pthread\u self()
    函数没有给出正确的
    线程ID
    ??当它在接收到
    信号后被调用时,@JishnuBanerjee
    pthread_self()
    将给出调用线程的线程id。但真正的问题是不可能有每线程信号处理程序;信号处理是全过程的。请参阅链接手册页中有关如何阻止信号的示例。C标准说:“在多线程程序中使用此函数[
    signal
    ]会导致未定义的行为。”这里如何准确地调用sig_handler()?我的意思是每次调用sig_handler()时,OP都会获得不同的threadID,即OP发送信号。这个特定的程序实际上是如何管理/处理这些信号的?OP发送的信号不是特定于线程的。这是全过程的。因此,您无法确定/知道信号发送到哪个线程
    pthreads(7)
    说:“POSIX.1区分了定向到整个进程的信号和定向到单个线程的信号的概念。根据POSIX.1,定向到进程的信号(例如,sentusing kill(2))应该由进程中任意选择的单个线程来处理。”“任意信号传递”意味着任何线程都可以接收信号并调用信号处理程序并打印其threadID。