pthread_kill 和 sigaction 函数

转载 2012年03月30日 17:19:47

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

intsigaction(int signo,conststruct sigaction*restrict act,

             struct sigaction*restrict oact);

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

结构sigaction定义如下:

structsigaction{
  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又叫做信号捕捉器, 这样进程捕捉到信号后就不会进行信号的默认操作了。)


Linux系统sigaction函数的使用示例

一、函数原型int sigaction(int signum, const struct sigaction *act, struct sigaction *...
  • u010889616
  • u010889616
  • 2015年09月01日 16:18
  • 4590

sigaction函数和signal函数

signal和sigaction的区别: signal都是指以前的older signal函数,现在大多系统都用sigaction重新实现了signal函数。 1.      signal在调用h...
  • jisuanji2121
  • jisuanji2121
  • 2013年03月13日 16:36
  • 3673

linux系统编程之信号(四):信号的捕捉与sigaction函数

一、内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 1. 用户程序注册了SI...
  • Simba888888
  • Simba888888
  • 2013年05月19日 11:30
  • 11762

信号编程之sigaction函数和sigqueue函数

函数介绍 包含头文件 功能:sigaction函数用于改变进程接收到特定信号后的行为。 原型: int sigaction(int signum,const struct sigaction *a...
  • lzjsqn
  • lzjsqn
  • 2016年12月09日 22:29
  • 733

sigaction 用法实例

sigaction,是为替代signal 来设计的较稳定的信号处理。 signal的使用比较简单。signal(signalNO,signalproc); 而signaction,则可以设置比...
  • imxiangzi
  • imxiangzi
  • 2015年05月19日 16:33
  • 1690

源码剖析signal和sigaction的区别

这两个函数都是Linux下注册信号处理函数有关,但是它们的区别一般我们都是从书上、网上、man手册得知,要想对它们的区别了然于胸,源码剖析才是彻底的方法。 先来看这两个函数的区别和实验: 1、sign...
  • wangzuxi
  • wangzuxi
  • 2015年04月01日 22:08
  • 2710

linux之信号处理函数signal和sigaction

signal回调函数绑定信号(signal)是一种软件中断,它提供了一种处理异步事件的方法,也是进程间惟一的异步通信方式。那么我们很多场景下,需要对不同的信号进行捕获并做出响应操作。 在linux上...
  • to_be_better
  • to_be_better
  • 2016年11月22日 03:20
  • 722

signal函数和sigaction结构体理解

signal函数和sigaction结构体理解 一,signal函数 详细介绍: http://blog.csdn.net/ta893115871/article/details/747509...
  • damotiansheng
  • damotiansheng
  • 2015年04月08日 11:52
  • 3426

为什么使用sigaction而非signal

所以希望能用相同方式处理信号的多次出现,最好用sigaction.信号只出现并处理一次,可以用signal.   signal函数每次设置具体的信号处理函数(非SIG_IGN)只能生效一次,每次在...
  • suifengpiao_2011
  • suifengpiao_2011
  • 2016年07月06日 12:15
  • 852

Linux信号signal介绍,signal()函数,sigaction()函数

signal( SIGINT, SigIntHandler ); /* Ctrl-C handler */       static int     b_ctrl_c = 0;       st...
  • gx19862005
  • gx19862005
  • 2013年12月10日 11:29
  • 2568
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:pthread_kill 和 sigaction 函数
举报原因:
原因补充:

(最多只允许输入30个字)