嵌入式Linux系统编程 — 6.3 kill、raise、alarm、pause函数向进程发送信号

目录

1 kill函数

1.1 kill函数介绍

1.2 示例程序

2  raise函数

2.1 raise函数介绍

2.2 示例程序

3 alarm函数

3.1 alarm函数介绍

3.2 示例程序

4 pause函数

4.1 pause函数介绍

4.2 示例程序


与 kill 命令相类似, Linux 系统提供了 kill()系统调用,一个进程可通过 kill()向另一个进程发送信号;除了 kill()系统调用之外, Linux 系统还提供了库函数 raise(),也可用于实现发送信号的功能。此外,系统调用 alarm()和 pause()函数也可进行发送信号的特殊操作。
 

1 kill函数

1.1 kill函数介绍

kill()系统调用可将信号发送给指定的进程或进程组中的每一个进程, 其函数原型如下所示:

#include <sys/types.h>
#include <signal.h>int kill(pid_t pid, int sig);
  • pid: 参数 pid 为正数的情况下,用于指定接收此信号的进程 pid;除此之外,参数 pid 也可设置为 0 或-1 以及小于-1 等不同值。
pid取值含义
正数则信号 sig 将发送到 pid 指定的进程
0则将 sig 发送到当前进程的进程组中的每个进程
-1

则将 sig 发送到当前进程有权发送信号的每个进程,但进程 1(init)除外

小于-1

将 sig 发送到 ID 为-pid 的进程组中的每个进程,

进程中将信号发送给另一个进程是需要权限的,并不是可以随便给任何一个进程发送信号,超级用户root 进程可以将信号发送给任何进程,但对于非超级用户(普通用户)进程来说,其基本规则是发送者进程的实际用户 ID 或有效用户 ID 必须等于接收者进程的实际用户 ID 或有效用户 ID。

  • sig: 参数 sig 指定需要发送的信号,也可设置为 0,如果参数 sig 设置为 0 则表示不发送信号,但任执行错误检查,这通常可用于检查参数 pid 指定的进程是否存在。
  • 返回值: 成功返回 0;失败将返回-1,并设置 errno。

1.2 示例程序

示例程序接受一个命令行参数作为要发送信号的进程ID:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>int main(int argc, char *argv[]) 
{// 检查参数数量if (argc != 2) {fprintf(stderr, "Usage: %s <pid>\n", argv[0]);exit(EXIT_FAILURE);}// 第一个参数是程序名,第二个参数是我们的进程IDpid_t target_pid = (pid_t)strtol(argv[1], NULL, 10);// strtol会设置errno,如果转换失败我们需要检查errnoif (errno == ERANGE || target_pid == (pid_t)-1) {perror("Invalid PID");exit(EXIT_FAILURE);}// 要发送的信号,这里我们发送SIGTERM信号int signal_to_send = SIGTERM;// 使用kill函数发送信号if (kill(target_pid, signal_to_send) == -1) {// 如果kill调用失败,打印错误消息并退出perror("Error sending signal");exit(EXIT_FAILURE);}printf("Signal %d sent to process %d\n", signal_to_send, target_pid);return 0;
}
  • 程序首先检查了命令行参数的数量,输入进程ID参数。
  • 使用strtol函数将命令行参数转换为pid_t类型的进程ID。strtol函数尝试将字符串转换为长整数,并允许我们指定基数(这里使用10进制)。检查strtol是否成功转换了字符串。如果转换失败或超出范围,errno会被设置为ERANGE。如果strtol返回(pid_t)-1,并且errno不是ERANGE,这意味着没有发生范围错误,但字符串可能不是一个有效的数字。
  • 使用kill()函数向转换得到的进程ID发送SIGTERM信号。如果信号发送成功,程序将打印一条消息,说明信号已经发送到指定的进程。

程序运行结果如下,可以看到kill没有权限的pid和不存在的pid会报错:

2  raise函数

2.1 raise函数介绍

raise()函数用于发送信号给自己,即发送信号给当前进程。raise()函数原型如下所示:

#include <signal.h>int raise(int sig)

  • sig指定要发送给当前进程的信号编号。
  • 返回值:如果成功,raise()返回0;如果失败,返回-1并设置errno以指示错误。

 raise()其实等价于:kill(getpid(), sig);

2.2 示例程序

以下是使用raise()函数在当前进程内发送信号的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>// 信号处理函数
void signal_handler(int sig) {printf("Signal %d caught by process %d\n", sig, getpid());
}int main() 
{// 设置信号处理函数struct sigaction sa;sa.sa_handler = signal_handler; // 指定信号处理器sigemptyset(&sa.sa_mask);       // 初始化信号集,屏蔽信号sa.sa_flags = 0;                // 无特殊标志// 为SIGUSR1信号设置信号处理函数if (sigaction(SIGUSR1, &sa, NULL) < 0) {perror("sigaction");exit(EXIT_FAILURE);}printf("Process %d is running, and will raise SIGUSR1 to itself.\n", getpid());// 使用raise发送SIGUSR1信号给自己if (raise(SIGUSR1) != 0) {perror("raise");exit(EXIT_FAILURE);}return 0;
}
  • 程序首先定义了一个signal_handler函数,用于处理SIGUSR1信号。
  • main函数中,使用sigaction()函数设置了SIGUSR1信号的处理器为signal_handler。然后,我们使用raise(SIGUSR1)向当前进程发送SIGUSR1信号。这将触发signal_handler函数的执行。
  • 如果raise()调用成功,程序将继续执行。如果失败,将打印错误消息并退出。

程序运行结果如下:

3 alarm函数

3.1 alarm函数介绍

alarm函数用于设置一个定时器的系统调用,当定时器到期时,将向进程发送SIGALRM信号。函数原型如下:

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

  • seconds指定定时器到期前的时间,以秒为单位。
  • 返回值alarm()函数返回在调用之前已经设置的任何定时器的剩余时间(以秒为单位)。如果之前没有设置定时器,或者定时器已经到期,返回0。

需要注意的是 alarm 闹钟并不能循环触发,只能触发一次,若想要实现循环触发,可以在SIGALRM 信号处理函数中再次调用 alarm()函数设置定时器。

3.2 示例程序

以下是使用alarm()函数发送信号的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>void handle_alarm(int sig) {printf("Timer expired, process %d received SIGALRM\n", getpid());exit(-1);
}int main() 
{struct sigaction sa;// 设置信号处理函数sa.sa_handler = handle_alarm;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;if (sigaction(SIGALRM, &sa, NULL) < 0) {perror("sigaction");exit(EXIT_FAILURE);}printf("Process %d will raise SIGALRM in 5 seconds\n", getpid());// 设置定时器,5秒后触发SIGALRMunsigned int remaining_time = alarm(5);if (remaining_time > 0) {printf("Previous timer had %u seconds remaining\n", remaining_time);}// 主循环,等待SIGALRM信号while(1) {// 这里可以执行其他任务,但在这个例子中,我们只是等待信号sleep(1); // 避免CPU占用过高}return 0;
}
  • 程序定义了一个handle_alarm函数来处理SIGALRM信号。
  • 使用sigaction()设置了SIGALRM的信号处理函数。
  • 使用alarm(5)设置了一个5秒的定时器。定时器到期后,将发送SIGALRM信号给当前进程。
  • 如果之前有设置定时器,alarm()会返回之前定时器的剩余时间。

程序运行结果如下:

4 pause函数

4.1 pause函数介绍

pause()函数一个系统调用,可以使得进程暂停运行、进入休眠状态,直到进程捕获到一个信号为止。pause()函数的原型如下:

#include <unistd.h>int pause(void);
  • 参数pause()函数不接受任何参数。

  • 返回值pause()函数在正常情况下不会返回,因为它会无限期地挂起执行。只有当进程收到一个信号并且该信号不是通过pause()调用捕获时,它才会返回。如果被信号中断,它返回-1并设置errnoEINTR

4.2 示例程序

 以下是使用pause()函数等待发送信号的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>void handle_signal(int sig) {printf("Received signal %d\n", sig);
}int main() 
{struct sigaction sa;// 设置信号处理函数sa.sa_handler = handle_signal;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;// 为SIGINT设置信号处理函数if (sigaction(SIGINT, &sa, NULL) < 0) {perror("sigaction");exit(EXIT_FAILURE);}printf("Process %d is pausing. Send SIGINT to continue.\n", getpid());// 挂起进程直到收到信号pause();printf("Process %d has been resumed.\n", getpid());return 0;
}
  • 程序定义了一个handle_signal函数来处理SIGINT信号。
  • 使用sigaction()设置了SIGINT的信号处理函数。
  • 调用pause()使进程挂起,等待接收信号。在这个例子中,我们等待SIGINT信号,这里由通过Ctrl+C触发。
  • 当进程收到SIGINT信号时,pause()返回,handle_signal函数被调用,然后进程继续执行。

程序运行结果如下:

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

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

相关文章

Chapter9 更复杂的光照——Shader入门精要学习笔记

Chapter9 更复杂的光照 一、Unity的渲染路径1.渲染路径的概念2.渲染路径的类型①前向渲染路径a. 前向渲染路径的原理b. Unity中的前向渲染c. 两种Pass ②延迟渲染路径a. 延迟渲染路径的原理b. Unity中的延迟渲染c. 两种Pass ③顶点照明渲染路径 二、Unity的光源类型1.光源类型①…

Webpack: 核心流程之Init、Make、Seal

概述 在前文中&#xff0c;我们了解了 Webpack 的基本应用、性能优化、Loader 与 Plugin 组件开发方方面面的知识&#xff0c;相信学习过这些内容之后&#xff0c;你已经对 Webpack 有相当深入的理解了&#xff0c;可以开始从更底层的视角&#xff0c;自底向上重新审视 Webpac…

直流电机介绍

一、引入 电机&#xff0c;即电动机&#xff08;motor&#xff09;俗称马达&#xff0c;是电能转化为机械能的总称&#xff0c;按工作原理分类电机可以分为&#xff1a;直流电机&#xff08;通过直流电源供电&#xff0c;依靠电刷和换向器改变电流方向&#xff0c;产生连续转动…

文献解读-长读长测序-第十四期|《作为了解棉花驯化的资源,印度棉(Gossypium herbaceum L. Wagad)基因组》

关键词&#xff1a;基因组&#xff1b;长读长测序&#xff1b;棉花基因组&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;The Gossypium herbaceum L. Wagad genome as a resource for understanding cotton domestication标题&#xff08;中文&#xff…

DBdoctor v3.2.2 版本发布,支持对sqlserver、vastbase的纳管!

DBdoctor 3.2.2版本新增PgSQL的索引推荐及性能审核功能&#xff1b;拓展了oracle的纳管版本并支持纳管oracle rac&#xff1b;新增对sqlserver、vastbase数据库的纳管支持&#xff1b;修复了体验官活动中大家提出的一系列体验问题。 详细更新内容如下&#xff1a; 功能优化 Pg…

贪心算法题目总结

1. 整数替换 看到这道题目&#xff0c;我们首先能想到的方法就应该是递归解法&#xff0c;我们来画个图 此时我们出现了重复的子问题&#xff0c;就可以使用递归&#xff0c;只要我们遇到偶数&#xff0c;直接将n除以2递归下去&#xff0c;如果是奇数&#xff0c;选出加1和减1中…

我在手提电脑上将大模型训练成了语文老师

&#xff08;图片由大模型生成&#xff0c;如有侵权&#xff0c;立删&#xff09; 记得一年多以前&#xff0c;和不少商家交流大模型解决方案时&#xff0c;他们谈到内部有很多的资料&#xff0c;可以对大模型进行训练&#xff0c;让大模型变得更有智慧&#xff0c;从而为客户…

Day9:逆波兰表达式求值150 滑动窗口最大值239 前 K 个高频元素347

题目150. 逆波兰表达式求值 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int evalRPN(vector<string>& tokens) {//使用栈来消除stack<string> st;for(int i0;i<tokens.size();i){if(tokens[i]""||tokens[i]"-"|…

创新赋能,高效二开!CRMEB 标准版 v5.4公测版发布

历经十年磨砺&#xff0c;CRMEB 标准版如今已成为众多技术开发者与企业二次开发、构建定制化项目的热门系统&#xff0c;其全开源无加密、功能齐全、独立部署的特质&#xff0c;造就了标准版系统方便二开的优势&#xff0c;不仅深受开发者喜爱&#xff0c;更因其实用性和可靠性…

运行vue : 无法加载文件 C:\Program Files\nodejs\node_global\vue.ps1,因为在此系统上禁止运行脚本。

报错背景: 重装了win10系统,然后准备安装Vue,这个时候我已经安装好了node.js和npm,输入node -v和npm -v都有正确输出,但是每次输入npm install -g vue/cli 安装的时候,就会报错. 大家安装node.js的时候最好就是默认路径(C:\Program Files\nodejs),别去修改不然很多报错.(个人…

Linux Centos7部署Zookeeper

目录 一、下载zookeeper 二、单机部署 1、创建目录 2、解压 3、修改配置文件名 ​4、创建保存数据的文件夹 ​5、修改配置文件保存数据的地址 ​6、启动服务 7、api创建节点 一、下载zookeeper 地址&#xff1a;Index of /dist/zookeeper/zookeeper-3.5.7 (apache.org…

名企面试必问30题(十五)——你的学历有点低,你怎么看?

1.思路 首先承认学历低这一事实&#xff1a;我坦诚地承认自己的学历相对较低。 后续解决方案&#xff1a;不过&#xff0c;我相信能力的展现不仅仅取决于学历。在过往的工作经历中&#xff0c;我积累了丰富的实践经验&#xff0c;培养了较强的学习能力和解决问题的能力。我会持…

两台电脑怎么传文件?干货分享教程

当需要在两台电脑之间传输文件时&#xff0c;有多种方便的方法可供选择&#xff0c;以下是一些常见的方式及教程&#xff1a; 使用局域网共享&#xff1a; 确保两台电脑连接在同一个局域网内。 在其中一台电脑上&#xff0c;设置要共享的文件夹。右键点击文件夹&#xff0c;选…

论文学习——使用基于多项式拟合的预测算法求解动态多目标问题

论文题目&#xff1a;Solving dynamic multi-objective problems using polynomial fitting-based prediction algorithm 使用基于多项式拟合的预测算法求解动态多目标问题&#xff08;Qingyang Zhang , Xiangyu He,Shengxiang Yang , Yongquan Dong , Hui Song , Shouyong Ji…

归并排序-MergeSort (C语言详解)

目录 前言归并排序的思想归并排序的递归法归并排序的非递归法归并排序的时间复杂度与适用场景总结 前言 好久不见, 前面我们了解到了快速排序, 那么本篇旨在介绍另外一种排序, 它和快速排序的思想雷同, 但又有区别, 这就是归并排序, 如下图, 我们对比快速排序与归并排序. 本…

Nacos配置中心客户端源码分析(二): 客户端和服务端交互

本文收录于专栏 Nacos 推荐阅读&#xff1a;Nacos 架构 & 原理 ⚠️&#xff1a;使用的Nacos版本为2.3.X 文章目录 前言一、NacosConfigLoader二、NacosConfigService三、ClientWorker四、服务端处理逻辑总结 前言 上篇文章我们简单看了看Nacos客户端在启动的时候&#xf…

远程抄表管理系统建设方案(Word原件)

远程抄表管理系统建设方案应涵盖智能表计安装、数据采集与传输、数据处理与分析三大核心环节。首先&#xff0c;安装智能表计以实时采集水、电、气等数据&#xff1b;其次&#xff0c;利用先进的通信技术&#xff08;如GPRS、LoRa等&#xff09;实现数据的稳定传输&#xff1b;…

c语言回顾-数组(全网最详细,哈哈哈)

目录 前言&#xff0c;和小编一起感受数组的魅力&#xff01;&#xff01;&#xff01; 1.数组的概念 2.一维数组的创建和初始化 2.1数组创建 2.2数组的初始化 2.3数组的类型 3.一维数组的使用 3.1数组下标 3.2数组元素的输入输出 小结&#xff1a; 4.一维数组在内存…

pycharm的usages在哪设置?

参考文章&#xff1a;https://blog.51cto.com/save/8961821 在代码编辑器&#xff08;如PyCharm或IntelliJ IDEA&#xff09;中&#xff0c;"1 usage"通常表示当前光标所在的代码元素&#xff08;如变量、函数、类等&#xff09;在其他地方被使用了一次。这个功能可…

什么是自动气象站呢

自动气象站&#xff0c;作为现代气象观测的重要工具&#xff0c;已经深入到我们生活的各个领域&#xff0c;从气象预报到农业生产&#xff0c;再到环境保护&#xff0c;自动气象站都发挥着不可或缺的作用。 自动气象站&#xff0c;顾名思义&#xff0c;是一种能够自动收集、处理…