Unix信号处理

信号的基本概念我已经在上一节中简单介绍了,大家可以去看我的上一篇博客:

Unix中的进程和线程-2-CSDN博客

1.信号的产生

kill函数:

#include <signal.h>
#include <fcntl.h>
#include<t_stdio.h>
//自定义信号处理函数,n为信号编号
void handle(int n){printf("this is a test..\n");return;}int main(void){//从父进程继承信号处理函数//采用默认处理方式signal(2,SIG_IGN);//改变2号进程的处理函数,忽略2号信号signal(3,handle);//对3号信号使用自定义处理函数pid_t pid = fork();if(pid==-1)E_MSG("fork",-1);while(1);return 0;
}

  1. signal(2,SIG_IGN):使用signal()函数,将2号信号(通常是SIGINT,即Ctrl+C)的处理方式设置为忽略(SIG_IGN)。这意味着当程序接收到Ctrl+C时,不会终止程序,而是忽略该信号。
  2. signal(3,handle):将3号信号的处理方式设置为调用自定义的信号处理函数handle。这表示当程序接收到3号信号时(例如Ctrl+\),会执行handle函数中定义的操作。
  3. pid_t pid = fork();:创建一个子进程。
  4. if(pid==-1)E_MSG("fork",-1);:如果fork()调用失败,输出错误消息并退出程序。
  5. while(1);:在这个循环中,父进程和子进程都会进入一个无限循环,使得程序一直处于运行状态。

这个程序主要演示了信号处理的基本用法,以及父子进程之间对信号处理函数的继承。通过signal()函数可以设置特定信号的处理方式,可以是忽略该信号、采用默认的处理方式,或者调用自定义的信号处理函数。

 kill函数的仿写:

#include<t_stdio.h>
#include<t_file.h>
#include <sys/types.h>
#include <signal.h>int main(int argc , char * argv[]){//将命令行的参数转化为整数类型kill (atoi(argv[2]),atoi(argv[1]));return 0;
}

 alarm函数:

alarm函数是一个用于在指定时间后发送信号的函数。它允许你在程序中设置一个定时器,当定时器计时时间到达后,系统会向当前进程发送一个 SIGALRM 信号。这通常用于实现超时控制或者周期性任务。

以下是 alarm 函数的声明:

#include <unistd.h>unsigned int alarm(unsigned int seconds);

alarm 函数接受一个 unsigned int 类型的参数 seconds,表示定时器的计时时间,单位是秒。当调用 alarm 函数后,系统会在指定的秒数之后向当前进程发送 SIGALRM 信号。

如果之前已经设置过定时器,调用 alarm 函数会取消之前的定时器,并设置新的定时器。如果 seconds 参数为 0,则之前设置的定时器会被取消,且不会设置新的定时器。

下面是一个简单的示例代码,演示了如何使用 alarm 函数实现一个定时器:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>void handler(int signum) {printf("Received SIGALRM signal.\n");// 处理定时器触发后的逻辑
}int main() {// 注册信号处理函数signal(SIGALRM, handler);printf("Setting up alarm for 5 seconds.\n");// 设置定时器为 5 秒alarm(5);// 进入一个无限循环while (1) {// 这里可以执行一些其他任务// 例如:等待用户输入等}return 0;
}

在这个示例中,首先注册了一个信号处理函数 handler,用于处理 SIGALRM 信号。然后调用 alarm(5) 设置了一个定时器,时间为 5 秒。当定时器计时时间到达时,系统会发送 SIGALRM 信号,进而触发信号处理函数 handler,在该处理函数中打印了一条消息。

  2.信号的暂停

如下:

#include<stdio.h>
#include <unistd.h>
#include<signal.h>
//信号处理函数
void handle(int n){}unsigned int t_sleeps(unsigned int seconds){alarm(2);//设置一个两秒闹钟pause();//停止进程return alarm(0);//取消原来的脑子,返回未决时间}int main(void){//不能忽略SIGALRM信号,这样pause会一直起作用,不会停止//signal(SIGALRM,SIG_IGN);signal(SIGALRM,handle);while(1){t_sleeps(2);printf("nihao...\n");}return 0;
}

  1. #include<stdio.h>:包含了标准输入输出的头文件。
  2. #include <unistd.h>:包含了UNIX标准的头文件,其中包括了alarm()pause()函数的声明。
  3. #include<signal.h>:包含了信号处理相关的头文件。
  4. void handle(int n){}:定义了一个空的信号处理函数handle(),用于处理信号。在这个示例中,它并没有实际功能。
  5. unsigned int t_sleeps(unsigned int seconds):定义了一个自定义的睡眠函数t_sleeps(),它接受一个参数seconds,表示睡眠的秒数,并返回一个unsigned int类型的值,表示剩余的未决定时间。
  6. alarm(2);:调用alarm()函数,设置一个两秒的定时器。这会在两秒后向进程发送一个SIGALRM信号。
  7. pause();:调用pause()函数,使进程暂停,等待信号的到来。当接收到信号后,进程会恢复执行。
  8. return alarm(0);:取消之前设置的闹钟,并返回未决定的时间。

main()函数中:

  • 注册了信号处理函数,将SIGALRM信号的处理方式设置为handle函数。这一步通常是为了确保程序在接收到SIGALRM信号时不会终止。
  • 使用一个无限循环,调用t_sleeps(2)函数,表示每隔两秒打印一次"nihao..."。

这个程序的主要目的是演示如何使用alarm()pause()函数实现一个自定义的睡眠函数。当调用t_sleeps()函数时,程序会暂停执行两秒钟,然后继续执行后续的代码。

 3.信号阻塞和信号集

 3.1信号集的常用操作:

#include<signal.h>
#include<t_stdio.h>int main(void){//定义信号集类型变量set__sigset_t set;//初始化setsigemptyset(&set);//将2号信号添加到信号集set中sigaddset(&set,2);sigaddset(&set,3);//测试3号信号是不是信号集中的一员int is=sigismember(&set,3);if(is==-1)E_MSG("sigismember",-1);if(is) printf("signum is member of set..\n");else printf("signum is not member of set..\n");//将3号信号从信号集中移除sigdelset(&set , 3);is=sigismember(&set,3);if(is==-1)E_MSG("sigismember",-1);if(is) printf("del signum is member of set..\n");else printf("del signum is not member of set..\n");return 0;
}

 信号的阻塞:

3.2进程的信号掩码集:

#include<t_stdio.h>
#include <asm-generic/signal-defs.h>
#include <bits/sigset.h>int main(void){//定义信号集的变量set__sigset_t set;//初始化setsigemptyset(&set);//将2,3,9号信号添加到信号集set中sigaddset(&set,2);sigaddset(&set,3);sigaddset(&set,9);//将set设置为进程的信号掩码集int sm=sigprocmask(SIG_SETMASK,&set,NULL);if(sm==-1)E_MSG("sigprocmask",-1);while(1){}return 0;
}
  1. __sigset_t set;:定义了一个变量 set,类型为 __sigset_t,这是一个用于表示信号集的数据结构。
  2. sigemptyset(&set);:使用 sigemptyset() 函数将信号集 set 清空,确保其中不包含任何信号。
  3. sigaddset(&set,2);sigaddset(&set,3); 和 sigaddset(&set,9);:使用 sigaddset() 函数向信号集 set 中添加信号。在这里,将信号2、3和9添加到 set 中,分别代表 SIGINTSIGQUIT 和 SIGKILL 信号。
  4. int sm=sigprocmask(SIG_SETMASK,&set,NULL);:使用 sigprocmask() 函数将 set 中的信号设置为进程的信号掩码集。SIG_SETMASK 表示设置当前信号掩码为 set 中包含的信号集合,即阻塞信号2、3和9。如果设置成功,sigprocmask() 返回0;否则返回-1,并且相应的错误信息会被设置到 errno 中。
  5. while(1){}:进入一个无限循环,使得程序一直处于运行状态,以保持信号掩码的设置。

3.3未决信号集:

#include<t_stdio.h>
#include<signal.h>
#include <asm-generic/signal-defs.h>
#include<unistd.h>int main(void){//定义信号集类型变量__sigset_t set , pset;//初始化信号集sigemptyset(&set);//添加信号到setsigaddset(&set,2);//将set设置为进程的信号掩码集int sm =sigprocmask(SIG_BLOCK,&set,NULL);if(sm==-1)E_MSG("sigismember",-1);while(1){sleep(1);//获取进程的未决信号集,pset存放的就是进程的未决信号集sigpending(&pset);int is=sigismember(&pset,2);if(is==-1)E_MSG("sigismemeber",-1);is? printf("yes..\n") : printf("no..\n");}return 0;
}
  1. 信号掩码集(signal mask): 信号掩码集是用于阻塞一组信号的,也就是说,被加入到该进程的信号掩码集中的信号,都会被阻塞,直到被从掩码集中移除。在你的代码中,通过sigprocmask(SIG_BLOCK,&set,NULL);将2号信号(SIGINT,即Ctrl+C触发的中断信号)加入到了掩码集中,从而阻塞了该信号。
  2. 未决信号集(pending signal): 未决信号集是指当前被阻塞,并且尚未处理的信号集合。只要这个信号在掩码集中,那么该信号一旦产生,就会被追加到未决信号集中,等待处理。在代码中,未决信号集的状态被周期性检查,并且每秒输出一次结果,显示2号信号是否存在于未决信号集中。 应用场景: 信号掩码集主要用于在处理某个信号时临时屏蔽其它会对当前处理过程产生干扰的信号,比如在处理某些复杂的业务逻辑或者关键数据更新时,防止被其它信号打断。 未决信号集则帮助我们得知哪些信号被阻塞且尚未得到处理,这对于调试程序,以及编写稳健的并发处理代码很有帮助。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/784282.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM--打造Private GPT需要知道的一些概念及术语

文章目录 大模型存储格式GGMLGGUF Embedding概念分类 术语LlamaindexLlamaCPPPoetryASGIFastAPIChromaQdrantgradioMRL 大模型存储格式 大模型的存储一个很重要的问题是它的模型文件巨大&#xff0c;而模型的结构、参数等也会影响模型的推理效果和性能&#xff0c;为了让大模型…

云服务器8核32G配置报价大全,腾讯云、阿里云和京东云

8核32G云服务器租用优惠价格表&#xff0c;云服务器吧yunfuwuqiba.com整理阿里云8核32G服务器、腾讯云8核32G和京东云8C32G云主机配置报价&#xff0c;腾讯云和京东云是轻量应用服务器&#xff0c;阿里云是云服务器ECS&#xff1a; 阿里云8核32G服务器 阿里云8核32G服务器价格…

鸿蒙手机cordova-plugin-camera不能拍照和图片不显示问题

鸿蒙手机cordova-plugin-camera不能拍照和图片不显示问题 一、运行环境 1、硬件 手机型号&#xff1a;NOVA 7 系统&#xff1a;HarmonyOS版本 4.0.0 2、软件 android SDK platforms&#xff1a;14.0(API Level 34)、13.0&#xff08;API Level 33&#xff09; SDK Build-T…

TCP长连接与短链接的区别

TCP短连接 在TCP短连接的通信模式中&#xff0c;每次通信都需要经历建立连接、传输数据和断开连接三个阶段。客户端和服务器每进行一次通信交互&#xff0c;就会建立一个新的连接&#xff0c;数据传输完成后立即断开连接。这种模式适用于请求次数不频繁、维持连接的开销大于重…

CentOS系统下Docker的安装教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

K8S之Secret的介绍和使用

Secret Secret的介绍Secret的使用通过环境变量引入Secret通过volume挂载Secret Secret的介绍 Secret是一种保护敏感数据的资源对象。例如&#xff1a;密码、token、秘钥等&#xff0c;而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使…

【Linux】TCP网络套接字编程+守护进程

文章目录 日志类&#xff08;完成TCP/UDP套接字常见连接过程中的日志打印&#xff09;单进程版本的服务器客户端通信多进程版本和多线程版本守护进程化的多线程服务器 日志类&#xff08;完成TCP/UDP套接字常见连接过程中的日志打印&#xff09; 为了让我们的代码更规范化&…

前缀树实现字典添加查询

. - 力扣&#xff08;LeetCode&#xff09; Trie&#xff08;发音类似 "try"&#xff09;或者说 前缀树 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&#xff0c;例如自动补完和拼写检查。 请你实现 T…

车载电子电器架构 —— 诊断数据库开发

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

Python 后端 Flask 使用 Flask-SocketIO、前端 Vue3 实现长连接 Websocket 通信详细教程(更新中)

Flask 安装 Flask-Socketio Flask-SocketIO 第三方库使 Flask 应用程序可以实现客户端和服务器之间的低延迟双向通信。客户端应用程序可以使用 Javascript、Python、C、Java 和 Swift 中的任何 SocketIO 客户端库或任何其他兼容客户端来建立与服务器的永久连接。 Flask-Socke…

价值投资已死,MEME币永生?

BOME和SLERF结束了疯狂拉升&#xff0c;市场再次经历和见证了又一轮暴富「淘金」&#xff0c;尽管MEME的热浪尚未彻底退去&#xff0c;但市场也短暂恢复了一些冷静。 除了感慨 “币圈一天&#xff0c;传统金融一年” 的涨幅和收益之外&#xff0c;不少「老韭菜」都在讨论一个问…

基于微信小程序的自习室预约系统的设计与实现

基于微信小程序的自习室预约系统的设计与实现 文章目录 基于微信小程序的自习室预约系统的设计与实现1、前言介绍2、功能设计3、功能实现4、开发技术简介5、系统物理架构6、系统流程图7、库表设计8、关键代码9、源码获取10、 &#x1f389;写在最后 1、前言介绍 伴随着信息技术…

AR-Net网络(图像篡改检测)

AR-Net网络 摘要AbstractAR-Net1. 文献摘要2. 研究背景3. 创新点4. AR-Net 网络架构5. 实验6. 结论总结 摘要 AR-Net使用自适应注意力机制来融合位置和通道维度的特征&#xff0c;使网络能够充分利用不同维度的被篡改特征&#xff0c;此外&#xff0c;AR-Net 改进了预测掩模&a…

民宿预定(源码+文档)

民宿预定系统&#xff08;小程序、ios、安卓都可部署&#xff09; 文件包含内容程序简要说明含有功能项目截图客户端注册页学生特权介绍页我的界面登录界面民宿界面推荐房形已完成订单首页邀请好友待支付页全部订单进行中订单 管理端关键字管理用户管理订单管理民宿管理 文件包…

【春秋云镜】CVE-2023-27179靶标Wp

0x01&#xff1a;漏洞点 他的标题已经告诉我们路径在哪里&#xff0c;所以我们直接访问/_admin/imgdownload.php OK啊白白的一片&#xff0c;直接丢Yakit里面去 教训他。 0x02&#xff1a;操作部分 报告长官&#xff0c;一切正常&#xff01;&#xff01;未发现连接错误&#…

C语言-malloc(申请函数)free(释放函数)

malloc和free的语法格式 malloc 函数是 C 语言标准库中的一个重要函数&#xff0c;用于动态分配内存。其语法如下&#xff1a; void *malloc(size_t size);这里的 void * 表示返回的是一个 void 类型的指针&#xff0c;实际上这个指针指向的是一个 char 类型的内存块。size_t …

HTTP/1.1 如何优化?(计算机网络)

有三种方法&#xff1a; 第一个思路是&#xff0c;通过缓存技术来避免发送 HTTP 请求。客户端收到第一个请求的响应后&#xff0c;可以将其缓存在本地磁盘&#xff0c;下次请求的时候&#xff0c;如果缓存没过期&#xff0c;就直接读取本地缓存的响应数据。如果缓存过期&#…

GridLayoutManager 中的一些坑

前言 如果GridLayoutManager使用item的布局都是wrap_cotent 那么会在布局更改时会出现一些出人意料的情况。&#xff08;本文完全不具备可读性和说教性&#xff0c;仅为博主方便查找问题&#xff09; 布局item: <!--layout_item.xml--> <?xml version"1.0&qu…

DAY10,DAY11|逆波兰表达式,有效括号,删除字符串中重复项

文章目录 232.用栈实现队列225.用队列实现栈20.有效的括号1047.删除字符串中的所有重复项150.逆波兰表达式 232.用栈实现队列 文档讲解&#xff1a;用栈实现队列 视频链接&#xff1a;代码随想录-用栈实现队列 状态&#xff1a;ok 思路&#xff1a; 用两个栈实现队列操作&…

大模型面试准备(十一):怎样让英文大语言模型可以很好的支持中文?

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…