当前位置: 首页 > news >正文

嵌入式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函数被调用,然后进程继续执行。

程序运行结果如下:

相关文章:

嵌入式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 命令相类似&#xff0c; Linux 系统提供了 kill()系统调用&#…...

Swoole实践:如何使用协程构建高性能爬虫

随着互联网的普及&#xff0c;web爬虫已经成为了一个非常重要的工具&#xff0c;它可以帮助我们快速地抓取所需要的数据&#xff0c;从而降低数据获取成本。在爬虫的实现中&#xff0c;性能一直是一个重要的考虑因素。swoole是一款基于php的协程框架&#xff0c;它可以帮助我们…...

基于人脸68特征点识别的美颜算法(一) 大眼算法 C++

1、加载一张原图&#xff0c;并识别人脸的68个特征点 cv::Mat img cv::imread("5.jpg");// 人脸68特征点的识别函数vector<Point2f> points_vec dectectFace68(img);// 大眼效果函数Mat dst0 on_BigEye(800, img, points_vec);2、函数 vector<Point2f&g…...

算法金 | 欧氏距离算法、余弦相似度、汉明、曼哈顿、切比雪夫、闵可夫斯基、雅卡尔指数、半正矢、Sørensen-Dice

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 抱个拳&#xff0c;送个礼 在算法模型构建中&#xff0c;我们经常需要计算样本之间的相似度&#xff0c;通常的做法是计算样本之间的距…...

项目实战--Spring Boot大数据量报表Excel优化

一、项目场景 项目中要实现交易报表&#xff0c;处理大规模数据导出时&#xff0c;出现单个Excel文件过大导致性能下降的问题&#xff0c;需求是导出大概四千万条数据到Excel文件&#xff0c;不影响正式环境的其他查询。 二、方案 1.使用读写分离&#xff0c;查询操作由从库…...

C#编程技术指南:从入门到精通的全面教程

无论你是编程新手&#xff0c;还是想要深化.NET技能的开发者&#xff0c;本文都将为你提供一条清晰的学习路径&#xff0c;从C#基础到高级特性&#xff0c;每一站都配有详尽解析和实用示例&#xff0c;旨在帮助你建立坚实的知识体系&#xff0c;并激发你对C#及.NET生态的热情。…...

Redis+定式任务实现简易版消息队列

Redis是一个开源的内存中数据结构存储系统&#xff0c;通常被用作数据库、缓存和消息中间件。 Redis主要将数据存储在内存中&#xff0c;因此读写速度非常快。 支持不同的持久化方式&#xff0c;可以将内存中的数据定期写入磁盘&#xff0c;保证数据持久性。 redis本身就有自己…...

学习在 C# 中使用 Lambda 运算符

在 C# 中&#xff0c;lambda 运算符 > 同时用于 lambda 表达式和表达式体成员。 1. Lambda 表达式 Lambda 表达式是一种简洁的表示匿名方法&#xff08;没有名称的方法&#xff09;的方法。它使用 lambda 运算符 >&#xff0c;可以读作“转到”。运算符的左侧指定输入参…...

数据结构和算法,单链表的实现(kotlin版)

文章目录 数据结构和算法&#xff0c;单链表的实现(kotlin版)b站视频链接1.定义接口&#xff0c;我们需要实现的方法2.定义节点&#xff0c;表示每个链表节点。3.push(e: E)&#xff0c;链表尾部新增一个节点4.size(): Int&#xff0c;返回链表的长度5.getValue(index: Int): E…...

Jdk17是否有可能代替 Jdk8

JDK发展历史和开源 2006年SUN公司开源JDK&#xff0c;成立OpenJDK组织。2009年Oracle收购SUN&#xff0c;加快JDK发布周期。Oracle JDK与OpenJDK功能基本一致&#xff0c;但Oracle JDK提供更长时间的更新支持。 JDK版本特性 JDK11是长期支持版本&#xff08;LTS&#xff09;…...

oca和 ocp有什么区别

OCA&#xff08;Oracle Certified Associate&#xff09;和OCP&#xff08;Oracle Certified Professional&#xff09;在Oracle的认证体系中是两种不同级别的认证&#xff0c;它们之间存在明显的区别。以下是对两者区别的详细解释&#xff1a; 认证级别&#xff1a; OCA&…...

煤矿安全大模型:微调internlm2模型实现针对煤矿事故和煤矿安全知识的智能问答

煤矿安全大模型————矿途智护者 使用煤矿历史事故案例,事故处理报告、安全规程规章制度、技术文档、煤矿从业人员入职考试题库等数据,微调internlm2模型实现针对煤矿事故和煤矿安全知识的智能问答。 本项目简介: 近年来,国家对煤矿安全生产的重视程度不断提升。为了确…...

C++中的C++中的虚析构函数的作用和重要性

在C中&#xff0c;虚析构函数&#xff08;virtual destructor&#xff09;的作用和重要性主要体现在多态和继承的上下文中。了解这一点之前&#xff0c;我们先简要回顾一下多态和继承的基本概念。 继承与多态 继承&#xff1a;允许我们定义一个基类&#xff08;也称为父类或超…...

机器学习 - 文本特征处理之 TF 和 IDF

TF&#xff08;Term Frequency&#xff0c;词频&#xff09;和IDF&#xff08;Inverse Document Frequency&#xff0c;逆文档频率&#xff09;是文本处理和信息检索中的两个重要概念&#xff0c;常用于计算一个词在文档中的重要性。下面是详细解释&#xff1a; TF&#xff08…...

因为自己淋过雨所以想给嵌入式撑把伞

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;新手学嵌入式&#xff0c;…...

《C++20设计模式》中单例模式

文章目录 一、前言二、饿汉式1、实现 三、懒汉式1、实现 四、最后 一、前言 单例模式定义&#xff1a; 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;其主要目的是确保一个类只有一个实例&#xff0c;并提供全局访问点来访问这个实例。…...

前端技术(说明篇)

Introduction ##编写内容&#xff1a;1.前端概念梳理 2.前端技术种类 3.前端学习方式 ##编写人&#xff1a;贾雯爽 ##最后更新时间&#xff1a;2024/07/01 Overview 最近在广州粤嵌进行实习&#xff0c;项目名称是”基于Node实现多人聊天室“&#xff0c;主要内容是对前端界…...

带电池监控功能的恒流直流负载组

EAK的交流和直流工业电池负载组测试仪对于测试和验证关键电力系统的能力至关重要&#xff0c;旨在实现最佳精度。作为一家客户至上的公司&#xff0c;我们继续尽我们所能应对供应链挑战&#xff0c;以提供出色的交货时间&#xff0c;大约是行业其他公司的一半。 交流负载组 我…...

关于Disruptor监听策略

Disruptor框架提供了多种等待策略&#xff0c;每种策略都有其适用的场景和特点。以下是这些策略的详细介绍及其适用场景&#xff1a; 1. BlockingWaitStrategy 特点&#xff1a; 使用锁和条件变量进行线程间通信&#xff0c;线程在等待时会进入阻塞状态&#xff0c;释放CPU资…...

大数据面试题之HBase(3)

HBase的预分区 HBase的热点问题 HBase的memstore冲刷条件 HBase的MVCC HBase的大合并与小合并&#xff0c;大合并是如何做的?为什么要大合并 既然HBase底层数据是存储在HDFS上&#xff0c;为什么不直接使用HDFS&#xff0c;而还要用HBase HBase和Phoenix的区别 HBase支…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...