Linux进程通信:信号相关函数

news2024/11/27 12:38:19

1. kill函数

#include<sys/types.h>
#include<signal.h>

int kill(pid_t pid, int sig);
/*
功能:
    给进程pid发送信号sig
参数:
    pid:取值有4种情况:
        > 0:将sig信号发送给进程号为pid的进程;
        = 0:将sig信号发送给当前进程组中的所有进程;
        = -1:将sig信号发送给系统内的所有进程;
        < -1:将sig信号发送给进程组号为pid绝对值的进程组中的所有进程。
    sig:信号。推荐使用信号宏。
返回值:
    成功:0;
    失败:-1
*/

a)root权限用户可给任意用户发信号,普通用户不可给root权限用户发信号;

b)普通用户不允许:kill -9 root用户进程的pid; 普通用户也不允许向其他普通用户发送信号终止其进程,只能向自己创建的进程发送信号;普通用户只能给自己的进程发送信号。

kill函数示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<signal.h>
#include<unistd.h>

int main(int argc, const char* argv[]) {

    pid_t pid = -1;
    int ret = -1;

    // 创建一个子进程
    pid = fork();
    if (-1 == pid) {
        perror("fork");
        return 1;
    }

    // 父进程杀死子进程
    if (pid > 0) {  // 父进程
        sleep(3);
        ret = kill(pid, SIGTERM);
        if (-1 == ret) {
            perror("kill");
            return 1;
        }
        printf("子进程被杀死!\n");
    } else {  // 子进程
        while (1) {
            printf("子进程运行中...\n");
            sleep(1);
        }
        exit(0);
    }

    return 0;
}

运行结果:


2. raise函数

#include<signal.h>

int raise(int sig);
/*
功能:
    当前进程给自己发送信号sig,相当于kill(getpid(), sig);
参数:
    sig:信号宏;
返回值:
    成功:0
    失败:非0
*/

raise函数示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<signal.h>
#include<unistd.h>

int main(int argc, const char* argv[]) {

    int i = 4;

    while (1) {
        printf("进程%d自杀倒计时: %d\n", getpid(), i);
        sleep(1);
        if (0== --i) {
            printf("进程%d杀死自己.\n", getpid());
            raise(SIGTERM);
        }
    }

    return 0;
}

运行结果:


 3. abort函数

#include<stdlib.h>

void abort(void);
/*
功能:
    给自己发送异常终止信号,即6号信号SIGABTR,并产生core文件。
    等价于kill(getpid(), SIGABRT);
*/

abort函数示例:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

int main(int argc, const char* argv[]) {

    int i = 3;

    while (1) {
        printf("终止倒计时:%d\n", i--);
        sleep(1);
        if (0 == i) {
            printf("进程终止!\n");
            abort();
        }
    }
    return 0;
}

运行结果:


4. alarm函数

定时器

#include<unistd.h>

unsigned int alarm(unsigned int seconds);
/*
功能:
    设置定时器:指定seconds后,内核给当前进程发送14号信号SIGALRM信号,
    进程收到该信号,默认终止进程。
    每个进程有且只有唯一的定时器。
参数:
    seconds:定时时间,单位s;
             为0时则表示取消定时器,并返回旧闹钟剩余秒数。
返回值:
    0或剩余秒数。
*/

注意:alarm函数与调用进程状态无关。进程处于任何状态(退出除外),alarm都会计时。

alarm函数示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main(int argc, const char* argv[]) {

    unsigned int ret = 0;

    ret = alarm(5);
    sleep(3); // 进程的sleep状态不会影响闹钟的计时

    ret = alarm(4); // 覆盖之前的闹钟,重新计时

    /* 结果为2. 第一次计时5秒,sleep了3秒,
    执行到第二个闹钟时,第一次闹钟剩余2s*/
    printf("上次闹钟剩下的时间:%u\n", ret);
    getchar();
    return 0;
}

运行结果:

 前后总共计时7s


5. setitimer函数

多功能定时器

#include<sys/time.h>

int setitimer(int which, const struct itimerval* new_value, struct itimerval* old_value);

struct itimerval {
    struct timerval it_value;    // 闹钟触发时间
    struct timerval it_interval; // 闹钟触发周期
}

struct timeval {
    long tv_sec;   // 秒
    long tv_usec;  // 微秒
}

/*
功能:
    设置定时器。可替代alarm,精度μs。可实现周期定时。
参数:
    which:定时方式:
        a) 自然定时:ITIMER_REAL(14号信号,SIGALRM),计算自然时间,默认终止进程;
        b) 虚拟空间计时(用户空间):ITIMER_VIRTUAL(26号信号,SIGVTALRM),只计算占CPU时间;
        c) 运行时计时(用户+内核):ITIMER_PROF(27号信号,SIGPROF),计算占用CPU+系统调用时间;
    new_value:超时时间;
        itimerval.it_value:第一次执行function延迟的秒数;
        itimerval.it_interval:以后执行function的时间间隔
    old_value:存放旧的timeout值,一般为NULL
返回值:
    成功:0;
    失败:-1
*/

setitimer示例:

#include<stdio.h>
#include<sys/time.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, const char* argv[]) {

    int ret = -1;

    struct itimerval tmo;

    // 第一次触发时间: 3s
    tmo.it_value.tv_sec = 3;
    tmo.it_value.tv_usec = 0;

    // 触发周期: 2s一次。 此处无效果,需结合后面的信号捕捉使用。
    tmo.it_interval.tv_sec = 2;
    tmo.it_interval.tv_usec = 0;

    // 设置定时器, 默认动作:终止进程
    ret = setitimer(ITIMER_REAL, &tmo, NULL);
    if (-1 == ret) {
        perror("setitimer");
        return 1;
    }

    printf("按下任意键继续\n");
    getchar();

    return 0;
}

运行结果:


6. signal函数

注册信号处理函数。

注:由于历史原因,signal函数在不同版本的类Unix系统中含义不同,应避免使用signal函数。

#include<signal.h>

typedef void(*sighandler_t)(int);
/*
函数指针。
名字:sighandler_t,返回值:void,形参:一个int类型;
*/

sighandler_t signal(int signum, sighandler_t handler);
/*
功能:
    注册信号处理函数:收到signum信号,则执行handler函数。
    不可用于SIGKILL、SIGSTOP信号。
参数:
    signum:信号编号,建议写信号的宏;
    handler:3中取值情况:
            SIG_IGN:忽略该信号;
            SIG_DFL:执行默认动作;
            回调函数:执行自定义函数
                    回调函数定义如下:
                        void func(int signo) {
                            // signo为触发的信号,为signal函数的第一个参数
                        }
返回值:
    成功:第一次返回NULL,下一次返回此信号上次注册的信号处理函数的地址;
        若需要使用此返回值,则必须在前面声明此函数的指针类型。
    失败:SIG_ERR
*/

signal示例1:

捕捉Ctrl+c、Ctrl+\信号。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<unistd.h>

void func0(int signum) {
    printf("捕捉到信号:%d\n", signum);
}

void func1(int signum) {
    printf("捕捉到信号:%d\n", signum);
}

int main(int argc, const char* argv[]) {

    /*注册信号处理函数。*/
    // SIGINT: Ctrl + c
    signal(SIGINT, func0); // 处理异步信号

    /*SIGQUIT: Ctrl + \*/
    signal(SIGQUIT, func1);

    while (1) {
        getchar();
    }

    return 0;
}

运行结果:

signal示例2:

捕捉setitimer信号,修改它默认终止进程的行为。

#include<stdio.h>
#include<sys/time.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>

void func(int signum) {
    printf("捕捉到SIGALRM信号.\n");
}

int main(int argc, const char* argv[]) {

    int ret = -1;

    struct itimerval tmo;

    // 第一次触发时间: 3s
    tmo.it_value.tv_sec = 3;
    tmo.it_value.tv_usec = 0;

    // 触发周期: 2s一次。 此处无效果,需结合后面的信号捕捉使用。
    tmo.it_interval.tv_sec = 2;
    tmo.it_interval.tv_usec = 0;

    // 捕捉信号SIGALRM
    signal(SIGALRM, func);

    // 设置定时器, 默认动作:终止进程
    ret = setitimer(ITIMER_REAL, &tmo, NULL);
    if (-1 == ret) {
        perror("setitimer");
        return 1;
    }

    printf("按下任意键继续\n");
    getchar();

    return 0;
}

运行结果:


7.    待补充...

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

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

相关文章

加密解密学习笔记

加密种类 对称加密&#xff0c;分组对称加密算法 加密算法 AES&#xff08;Advanced Encryption Standard&#xff09;高级加密标准 DES&#xff08;Data Encryption Standard&#xff09;数据加密标准 3DES/Triple DEA (Triple Data Encryption Algorithm) 三重数据加密算…

如何分别在macOSWindowsLinux上对OpenSSL源码进行编译

问题描述 如何分别在macOS、Windows、Linux系统上对OpenSSL源码进行编译&#xff1f; 问题解答 编译版本&#xff1a;openssl-1.1.1t 官方源码地址&#xff1a;https://www.openssl.org/source/ 下面流程在三种系统上均进行实际验证&#xff0c;可放心食用。 Windows(MSVC…

在Vue3项目中js-cookie库的使用

文章目录 前言1.安装js-cookie库2.引入、使用js-cookie库 前言 今天分享一下在Vue3项目中引入使用js-cookie。 1.安装js-cookie库 js-cookie官网 安装js-cookie&#xff0c;输入 npm i js-cookie安装完成可以在package.json中看到&#xff1a; 安装以后&#xff0c;就可…

【C++代码之美】你不得不知道的经典代码

1.斐波那契数列 斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列&#xff0c;因数学家莱昂纳多斐波那契&#xff08;Leonardo Fibonacci&#xff09;以兔子繁殖为例子而引入&#xff0c;故又称为“兔子数列”&#xff0c;指的是这样一个…

vite4+vue3:从0到1搭建vben后台管理系统

从0到1带你学习如何搭建vben后台管理系统系列文章目录 一.准备工作:技术选型基础环境的搭建 文章目录 从0到1带你学习如何搭建vben后台管理系统系列文章目录一.准备工作:技术选型基础环境的搭建 前言一、技术选型二、生成基础项目三、安装步骤跑起项目 总结 前言 前端日趋复杂…

鸿蒙Hi3861学习二-程序烧录与日志输出

一、准备事项 开发板&#xff1a;BearPi-Hm Nano windows工具&#xff1a;HiBurn.exe https://pan.baidu.com/s/18OQD1_BvjNKD_J2e2iX3qg?pwdadrs 提取码&#xff1a;adrs windows工具&#xff1a;MobaXterm和RaiDrive 把ubuntu文件夹映射到windows本地。可以参考如下链接&am…

边缘计算在哪些场景的应用?实现了哪些功能

边缘计算是一种分布式计算模型&#xff0c;将数据处理和存储功能从云中心移动到接近数据源的边缘设备上&#xff0c;从而在处理延迟、网络带宽、隐私保护和数据安全等方面带来了许多优势。 智慧油站应用&#xff1a;在加油区部署的吸烟检测、打电话检测、烟火检测、区域入侵检测…

Mybatis-Flex快速入门教程

目录 一、Mybatis-Flex是什么&#xff1f; 二、Mybatis-Flex的有什么特点&#xff1f; 三、Mybatis-Flex和同类框架对比 四、Mybatis-Flex支持的数据库类型 五、快速入门 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;创建数据库 &#xff08;3&#…

攀高识别预警系统 yolov7

攀高识别预警系统通过yolov7网络模型技术&#xff0c;攀高识别预警系统对人员违规抽烟、打架斗殴、异常倒地、翻越围墙、异常聚集、打电话、区域侵入等行为分析等立即抓拍及时触发告警。YOLOv7 的发展方向与当前主流的实时目标检测器不同&#xff0c;研究团队希望它能够同时支持…

【5. ROS机器人的运动控制】

【ROS机器人的运动控制】 1. 前言2. 机器人的运动3. 机器人的运动速度单位4. geometry_msgs模型5. 用C实现机器人运动控制5.1 新建vel_pkg包5.2 编写vel_node.cpp代码5.3 设置编译规则5.4 运行验证 6. 用python实现机器人运动控制6.1 新建vel_pkg包6.2 编写vel_node.py代码6.3 …

[开源工具]Win10/11/8/7 获取笔记本电脑连接过的WIFI名称和密码[开箱可用]

[开源工具]Win10/11/8/7 获取笔记本电脑连接过的WIFI名称和密码[开箱可用] 1.打开命令提示符(管理员身份)2.输入netsh wlan show profile3.输入netsh wlan export profile folderC:\ keyclear4.打开C盘5.使用记事本打开 查看WIFI名称和密码 1.打开命令提示符(管理员身份) 首先…

计算机网络-应用协议与数据包分析实验(使用Wireshark)

实验一.应用协议与数据包分析实验(使用Wireshark) 一.实验目的 通过本实验&#xff0c;熟练掌握Wireshark的操作和使用&#xff0c;学习对HTTP协议进行分析。 二.实验内容 学习http协议&#xff0c;使用Wireshark截获http报文&#xff0c;对http请求报文和响应报文进行分析。…

【ONE·C++ || 多态】

总言 主要介绍多态相关内容。 文章目录 总言1、多态介绍1.1、多态是什么1.2、构成多态的两个必备条件1.2.1、虚函数介绍1.2.2、基类的指针或者引用调用虚函数1.2.3、演示多态条件的破坏&#xff08;两个特例说明&#xff09;1.2.3.1、不符合条件演示1.2.3.2、特例演示 1.3、一…

【高危】Spring Boot在Cloud Foundry中部署存在路由限制绕过风险(CVE-2023-20873)

漏洞描述 Spring Boot是用于构建Java应用程序的框架&#xff0c;Cloud Foundry是用于部署和管理应用程序的云平台&#xff0c;/cloudfoundryapplication也会路由至Spring Boot actuator。 当 Spring Boot 的受影响版本部署在 Cloud Foundry 上且具有处理 /cloudfoundryapplic…

计算机网络-应用层和传输层协议分析实验(PacketTracer)

实验三.应用层和传输层协议分析实验 一.实验目的 通过本实验&#xff0c;熟悉PacketTracer的使用&#xff0c;学习在PacketTracer中仿真分析应用层和传输层协议&#xff0c;进一步加深对协议工作过程的理解。 二.实验内容 从 PC 使用 URL 捕获 Web 请求&#xff0c;运行模拟并…

第06讲:为何各大开源框架专宠 SPI 技术?

在此前的内容中&#xff0c;已经详细介绍了 SkyWalking Agent 用到的多种基础技术&#xff0c;例如&#xff0c;Byte Buddy、Java Agent 以及 OpenTracing 中的核心概念。本课时将深入介绍 SkyWalking Agent 以及 OAP 中都会使用到的 SPI 技术。 JDK SPI 机制 SPI&#xff08…

Oracle-12c版本之后替换OCR磁盘组步骤

背景: 用户有一套Oracle12.2的RAC集群&#xff0c;在安装配置的时候&#xff0c;OCR磁盘只使用了单块磁盘external的模式&#xff0c;想替换成包含三块磁盘组成员normal模式的磁盘组 OCR磁盘组存储的对象: 在替换OCR磁盘之前&#xff0c;我们先确认需要迁移的OCR磁盘组存储的对…

图扑数字孪生助力智慧冷链园区实现大数据实时监控

前言 近年来&#xff0c;业界学者及企业就智慧冷链物流展开深入研究&#xff0c;2010 年 IBM 发布的《智慧的未来供应链》研究报告中提出智慧供应链概念&#xff0c;并由此延伸出智慧物流概念&#xff0c;即智慧物流是以信息化为依托并广泛应用物联网、人工智能、大数据、云计…

设置rocky Linux ip 与主机服务器处于同一网段内,并且能上网

第一步&#xff1a;查找主机服务器的 了解地址信息 第二步&#xff0c;设置rocky Linux 网络适配器连接&#xff0c;选择桥接模式 第三步&#xff1a;设置rocky Linux ip 第四步&#xff0c;设置完&#xff0c;重启Linux &#xff0c;验证ip是否修改过来&#xff0c;是否在同一…

【python】scikit-learn包:模型评估与优化

模型构建的目的 首先明确&#xff0c;模型拟合的目的&#xff1a; 不是对训练数据进行准确预测&#xff0c;而是对新数据进行准确预测 欠拟合 与 过拟合 欠拟合&#xff1a;可以通过训练数据及时发现&#xff0c;且可通过优化模型结果解决 过拟合&#xff1a;难以发觉&#x…