zoukankan      html  css  js  c++  java
  • pthread_kill 和 sigaction 函数(摘抄)

    摘抄来的文章
    原文链接:
    pthread_kill 和 sigaction 函数
    2009-06-14 18:45

    pthread_kill:

    别被名字吓到,pthread_kill可不是kill,而是向线程发送signal。还记得signal吗,大部分signal的默认动作是终止进程的运行,所以,我们才要用signal()去抓信号并加上处理函数。

    int pthread_kill(pthread_t thread, int sig);

    向指定ID的线程发送sig信号,如果线程代码内不做处理,则按照信号默认的行为影响整个进程,也就是说,如果你给一个线程发送了SIGQUIT,但线程却没有实现signal处理函数,则整个进程退出。

    pthread_kill(threadid, SIGKILL)也一样,杀死整个进程。
    如果要获得正确的行为,就需要在线程内实现signal(SIGKILL,sig_handler)了。

    所以,如果int sig的参数不是0,那一定要清楚到底要干什么,而且一定要实现线程的信号处理函数,否则,就会影响整个进程。


    OK,如果int sig是0呢,这是一个保留信号,一个作用是用来判断线程是不是还活着。

    我们来看一下pthread_kill的返回值:
    成功:0
    线程不存在:ESRCH
    信号不合法:EINVAL

    所以,pthread_kill(threadid,0)就很有用啦。

    int kill_rc = pthread_kill(thread_id,0);

    if(kill_rc == ESRCH)
        printf("the specified thread did not exists or already quit\n");
    else if(kill_rc == EINVAL)
        printf("signal is invalid\n");
    else
        printf("the specified thread is alive\n");

    上述的代码就可以判断线程是不是还活着了。

    sigaction :

    信号安装函数sigaction(int signum,const struct sigaction *act,struct sigaction *oldact)

    sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。

    他是POSIX的信号接口,而signal()是标准C的信号接口(如果程序必须在非POSIX系统上运行,那么就应该使用这个接口)

    给信号signum设置新的信号处理函数act, 同时保留该信号原有的信号处理函数oldact

    int sigaction(int signo,const struct sigaction *restrict act,

                  struct sigaction *restrict oact);

    sigaction函数是把SIGINT中断信号改变,通过act.sa_handler转到新的操作上。

    结构sigaction定义如下:

    struct sigaction{
      void (*sa_handler)(int);
       sigset_t sa_mask;
      int sa_flag;
      void (*sa_sigaction)(int,siginfo_t *,void *);
    };

    sa_handler字段包含一个信号捕捉函数的地址

    sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

    sa_flag是一个选项,主要理解两个

    SA_INTERRUPT 由此信号中断的系统调用不会自动重启
    SA_RESTART 由此信号中断的系统调用会自动重启

    SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

    最后一个参数是一个替代的信号处理程序,当设置SA_SIGINFO时才会用他。

    例子:

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

    void show_handler(int sig)
    {
        printf("I got signal %d\n", sig);
        int i;
        for(i = 0; i < 5; i++) {
            printf("i = %d\n", i);
            sleep(1);
        }
    }

    int main(void)
    {
        int i = 0;
        struct sigaction act, oldact;
        act.sa_handler = show_handler;
        sigaddset(&act.sa_mask, SIGQUIT); //见注(1)
        act.sa_flags = SA_RESETHAND | SA_NODEFER; //见注(2)
        //act.sa_flags = 0; //见注(3)

        sigaction(SIGINT, &act, &oldact);
        while(1) {
            sleep(1);
            printf("sleeping %d\n", i);
            i++;
        }
    }

    注:
    (1)    如果在信号SIGINT(Ctrl + c)的信号处理函数show_handler执行过程中,本进程收到信号SIGQUIT(Crt+\),将阻塞该信号,直到show_handler执行结束才会处理信号SIGQUIT。
    (2)    SA_NODEFER       一般情况下, 当信号处理函数运行时,内核将阻塞<该给定信号 -- SIGINT>。但是如果设置了SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号。 SA_NODEFER是这个标记的正式的POSIX名字(还有一个名字SA_NOMASK,为了软件的可移植性,一般不用这个名字)    
           SA_RESETHAND    当调用信号处理函数时,将信号的处理函数重置为缺省值。 SA_RESETHAND是这个标记的正式的POSIX名字(还有一个名字SA_ONESHOT,为了软件的可移植性,一般不用这个名字)   
    (3)    如果不需要重置该给定信号的处理函数为缺省值;并且不需要阻塞该给定信号(无须设置sa_flags标志),那么必须将sa_flags清零,否则运行将会产生段错误。但是sa_flags清零后可能会造成信号丢失!


    附:(导航项目中的一个例子)

    目标:想建立个函数,实时监测某个“START”信号,然后周期性地做数据采集动作;并且能够监测“STOP”信号,结束采集。(开始或结束信号是由主程序发出的) 

    实现方法:

    在主程序中创建一个线程。

    1.监测“START”信号:线程一开始就调用pthread_cond_wait(cond, mutex)挂起,主程序的“START”信号可以通过pthread_cond_signal(cond)发出;

    2.监测“STOP”信号:主程序调用pthread_kill(*threadID,SIG_num)发出结束信号,然后在接收信号的线程设置捕捉该信号的处理函数。

    struct sigaction sighandler; 
    sighandler.sa_handler = stopfunction; 
    sigaction(SIG_num,&sighandler,NULL); 
    在函数stopfunction里边添加退出时要做的事情。 
    执行该函数之后该线程可以任意做其他的事情。 
    同时可以随时接收thread_kill信号执行stopfunction。

    (解析:自己定义的函数stopfunction又叫做信号捕捉器, 这样进程捕捉到信号后就不会进行信号的默认操作了。)

  • 相关阅读:
    使用golang访问kubebernetes
    使用 Rancher 管理现有 Kubernetes 集群
    Running powershell scripts during nuget package installation and removal
    How to Create, Use, and Debug .NET application Crash Dumps in 2019
    寻找写代码感觉(一)之使用 Spring Boot 快速搭建项目
    Selenium+Java之解决org.openqa.selenium.InvalidArgumentException: invalid argument报错问题
    Selenium环境搭建
    关于Xpath定位方法知道这些基本够用
    Web自动化之浏览器启动
    【翻译】编写代码注释的最佳实践
  • 原文地址:https://www.cnblogs.com/resound/p/2117243.html
Copyright © 2011-2022 走看看