pthread_kill函数 和 sigaction 函数

pthread_kill:

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

向指定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)就很有用啦。

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

sigaction :

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


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

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

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


 
 

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

结构sigaction定义如下:

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

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

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

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

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

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

例子:

注:
(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)发出结束信号,然后在接收信号的线程设置捕捉该信号的处理函数。

在函数stopfunction里边添加退出时要做的事情。
执行该函数之后该线程可以任意做其他的事情。
同时可以随时接收thread_kill信号执行stopfunction。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/liuweikai1338/archive/2009/12/04/4941624.aspx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当我们调用pthread_kill函数向一个线程发送信号时,如果该线程没有设置对该信号的处理函数,则该信号会被默认处理。如果该线程设置了对该信号的处理函数,则该处理函数会被调用。 对于线程的信号处理函数,有以下几个注意点: 1. 信号处理函数需要使用sigaction函数进行注册,而不能使用signal函数; 2. 信号处理函数需要是一个void类型的函数,参数为int类型; 3. 信号处理函数需要在一定时间内执行完毕,否则可能会被操作系统强制终止; 4. 在信号处理函数中,为了避免竞态条件,需要避免使用非线程安全的函数和数据结构。 例如,以下是一个简单的线程信号处理函数的示例: ```c void sig_handler(int signum) { printf("Received signal %d\n", signum); // do something } int main() { pthread_t tid; int ret; // 创建线程 ret = pthread_create(&tid, NULL, thread_func, NULL); if (ret != 0) { printf("pthread_create error\n"); return -1; } // 向线程发送信号 ret = pthread_kill(tid, SIGINT); if (ret != 0) { printf("pthread_kill error\n"); return -1; } // 等待线程退出 ret = pthread_join(tid, NULL); if (ret != 0) { printf("pthread_join error\n"); return -1; } return 0; } void *thread_func(void *arg) { // 注册信号处理函数 struct sigaction act; act.sa_handler = sig_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); // 等待信号 while (1) { sleep(1); } return NULL; } ``` 在该示例中,我们创建了一个线程,并向该线程发送了一个SIGINT信号。该线程的信号处理函数简单地打印了接收到的信号编号。注意,该线程的信号处理函数需要先使用sigaction函数进行注册。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值