热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux多线程34_向线程发送信号

一、发送信号的函数intpthread_kill(pthread_tthread,intsig);1、别被名字吓到,pthread_kill可不是killÿ

一、发送信号的函数

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

​ 2、向指定ID的线程发送sig信号,如果线程代码内不做处理,则按照信号默认的行为影响整个进程,也就是说,如果你给一个线程发送了SIGQUIT,但线程却没有实现signal处理函数,则整个进程退出。如果要获得正确的行为,就需要在线程内实现sigaction了。所以,如果int sig的参数不是0,那一定要清楚到底要干什么,而且一定要实现线程的信号处理函数,否则,就会影响整个进程。如果int sig是0呢,这是一个保留信号,其实并没有发送信号,作用是用来判断线程是不是还活着。


二、信号处理

1、进程信号处理:
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
给信号signum设置一个处理函数,处理函数在sigaction中指定
act.sa_mask 信号屏蔽字
act.sa_handler 信号集处理程序

​ 2、信号集的处理

int sigemptyset(sigset_t *set); //清空信号集
int sigfillset(sigset_t *set); //将所有信号加入信号集
int sigaddset(sigset_t *set, int signum); //增加一个信号到信号集
int sigdelset(sigset_t *set, int signum); //删除一个信号到信号集

​ 3、多线程信号屏蔽处理
​ /* int sigprocmask(int how, const sigset_t *set, sigset_t oldset)/这是进程的信号屏蔽处理

int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
how = SIG_BLOCK:向当前的信号掩码中添加set,其中set表示要阻塞的信号组。
SIG_UNBLOCK:向当前的信号掩码中删除set,其中set表示要取消阻塞的信号组。
SIG_SETMASK:将当前的信号掩码替换为set,其中set表示新的信号掩码。
在多线程中,新线程的当前信号掩码会继承创造它的线程的信号掩码。
一般情况下,被阻塞的信号将不能中断此线程的执行,除非此信号的产生是因为程序运行出错如 SIGSEGV;另外不能被忽略处理的信号 SIGKILL 和 SIGSTOP 也无法被阻塞。


三、实例

#include
#include
#include
#include #include
#include #include "include/pthread.h"#ifndef _WIN64
#pragma comment(lib,".\\lib32\\pthreadVC2.lib")
#pragma comment(lib,".\\lib32\\pthreadVCE2.lib")
#pragma comment(lib,".\\lib32\\pthreadVSE2.lib")
#else
#pragma comment(lib,".\\lib64\\pthreadVC2.lib")
#endif /*
WINDOWS 缺少库函数,得在Linux下运行*DECRIPTION: 正确到处理信号* int pthread_kill(pthread_t thread, int sig);
* 向线程thread发送sig信号,成功返回0,失败返回错误码
*
* int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
* 为信号signum设置处理函数,处理函数在sigaction中指定
* act.sa_mask 信号屏蔽字
* act.sa_handler 信号集处理程序
*
* int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
* 多线程信号屏蔽函数
* how = SIG_BLOCK:向当前的信号掩码中添加set,其中set表示要阻塞的信号组。
* SIG_UNBLOCK:向当前的信号掩码中删除set,其中set表示要取消阻塞的信号组。
* SIG_SETMASK:将当前的信号掩码替换为set,其中set表示新的信号掩码。
* 在多线程中,新线程的当前信号掩码会继承创造它的线程的信号掩码
*/
void sig_handler1(int arg)
{printf("thread1 get signal\n");return;
}
void sig_handler2(int arg)
{printf("thread2 get signal\n");return;
}
void* thread_fun1(void* arg)
{printf("new thread 1\n");struct sigaction act;memset(&act, 0, sizeof(act));sigaddset(&act.sa_mask,SIGQUIT);act.sa_handler = sig_handler1;sigaction(SIGQUIT,&act,NULL);pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);Sleep(2);return (void*)0;
}
void *thread_fun2(void *arg)
{printf("new thread 2\n");//WINDOWS 缺少库函数,得在Linux下运行struct sigaction act;memset(&act, 0, sizeof(act));sigaddset(&act.sa_mask, SIGQUIT);act.sa_handler = sig_handler2;sigaction(SIGQUIT, &act, NULL);// pthread_sigmask(SIG_BLOCK, &act.sa_mask, NULL);Sleep(2);
}int main()
{pthread_t tid1, tid2;int err;int s;err = pthread_create(&tid1,NULL,thread_fun1,NULL);if (err!=0){printf("create new thread 1 failed\n");return 0;}err = pthread_create(&tid2,NULL,thread_fun2,NULL);if (err != 0){printf("create new thread 2 failed\n");return 0;}Sleep(1);s = pthread_kill(tid1, SIGQUIT);if (s!=0){printf("send signal to thread1 failed\n");}s = pthread_kill(tid2, SIGQUIT);if (s != 0){printf("send signal to thread2 failed\n");}pthread_join(tid1, NULL);pthread_join(tid2, NULL);return 0;
}

推荐阅读
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
author-avatar
冬天的芦苇2011
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有