【Linux】进程信号,相关函数的简单实用

这篇具有很好参考价值的文章主要介绍了【Linux】进程信号,相关函数的简单实用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。




一、讨论范围

【Linux】进程信号,相关函数的简单实用,linux,c++

  • 编号34以上的信号叫做实时信号,不在讨论范围内
  • 上图中信号的产生方式和默认处理动作可以通过
    man 7 signal指令来查看

二、信号的结构

1.信号的本质

task_struct内部存在一个位图结构,用int表示:uint32_t signals;
0000 0000 0000 0000 0000 0000 0000 0000

所谓的发送信号其实就是修改特定进程信号位图的特定比特位

  • 比特位的位置就是信号的编号
  • 比特位的内容表示1是否收到信号

2.预备知识

2.1 如何发送信号

kill options PID
其中,PID是进程的ID,可以是单个进程的ID,也可以是多个进程的ID,用空格分隔

eg:
给ID为1234的进程发送2号信号
kill -2 1234

该处使用的url网络请求的数据。

2.2 如何查看后台程序

ps aux | grep 名称关键词

eg:
查找名称与“chrome”相关的后台程序
ps aux | grep chrome


三、改变信号默认触发方式的两个函数

举个例子,在我们不小心写出死循环,或者故意写出死循环以便于使程序持续运行的时候,通常会在命令行输入“Ctrl+C”来停止命令行的无限刷屏,而我们输入的“Ctrl+C”,实际上就是给我们提到的死循环程序发送了2号信号;
下面是两个函数,它们的功能可以让一个程序在接收到2号信号时继续运行,而不是就此退出

1.signal

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

功能为“在收到signum号信号的时候执行handler函数”

eg:signal(2,handler) signal(SIGQUIT,handler)
两种写法都可以,signum可以是除了SIGKILL和SIGSTOP以外的任何有效信号

示例代码:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sigcb()
{
    printf("SIGINT\n");
}
int main()
{
    signal(SIGINT,(sighandler_t)sigcb);
    while(1)
    {

        printf("m alive\n");
        sleep(2);
    }
    return 0;
}

运行结果:
【Linux】进程信号,相关函数的简单实用,linux,c++
按下“Ctrl+C”也会有类似的结果
【Linux】进程信号,相关函数的简单实用,linux,c++

自己想试一下的话后面可以用“Ctrl+Z”结束这个程序,向它发送9号信号也可以,因为SIGKILL和SIGSTOP这个两个信号不能被系统忽略,也不能被改变默认处理动作

man一下之后可以发现使用文档表示这个函数已经过时了,而且不同系统版本下signal函数的功能也可能不一样

2.sigaction

#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

也是用来改变进程对于已接收信号做出的行动;
signum可以是任何除了SIGKILL和SIGSTOP以外的有效信号;
如果act不是NULL,则从act安装信号signum的新动作。如果oldact不是NULL,先前的操作保存在oldact中。

所以为了使用这个函数,struct sigaction的结构也必须了解

The sigaction structure is defined as something like:
           struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };
  • sa_handler就是接收到signum信号以后被调用的新方法,使用的时候先声明一个这样的结构体,然后再把函数指针指向你想要的函数就好了
  • 不要同时给sa_handler和sa_sigaction同时赋值
  • sa_restorer这个成员已经过时了,别用
  • 如果sa_flags被指定为SA_SIGINFO,收到signum对应的信号以后就执行sa_sigaction指向的函数(sa_handler这时候就没用了),这个函数把int作为其第一个参数,一个指向siginfo_t的指针作为其第二个参数,并将指向ucontext_t(强制转换为void *)的指针作为其第三个参数。(通常,handler函数不使用第三个参数)
  • sa.sa_flags = 0; 表示将 sa_flags 字段设置为零,表示使用默认的标志位,即默认的信号处理行为。

示例代码:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sigcb(int m)//为了不报错所以弄成了和结构体中指针相匹配的类型
{
    printf("SIGINT\n");
}
int main()
{
    struct sigaction m;
    m.sa_handler=sigcb;
    sigaction(SIGINT,&m,NULL);
    while(1)
    {
        printf("m alive\n");
        sleep(1);
    }
    return 0;
}

运行结果:
【Linux】进程信号,相关函数的简单实用,linux,c++

四、信号集操作函数和相关指令

这里的“信号集操作函数”指的就是用来操作signal mask的函数;
在 Unix 系统中,每个进程都有一个信号掩码signamask,用于管理它希望阻塞或允许传递的信号。sigprocmask 函数允许程序员操作这个信号掩码,以便选择性地阻塞或解除阻塞特定的信号。

#include <signal.h>

用起来也是事先声明好一个sigset_t类型的信号集``

0.sigprocmask

int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

oldset用来存储set的前一个值,也就是说如果oldset为非null,则信号掩码的前一个值存储在oldset中。
如果set为NULL,则信号掩码不变(忽略how),信号掩码的当前值仍然在oldset中返回(如果oldset不是的话)
参数how的参数:
【Linux】进程信号,相关函数的简单实用,linux,c++

1.sigemptyset

int sigemptyset(sigset_t *set);

函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有效信号。

2.sigaddset

int sigaddset (sigset_t *set, int signo);

添加一个signo信号到set这个信号集里面,使signo这个信号变成可以接收到的有效信号

3.sigdelset

int sigdelset(sigset_t *set, int signo);

把set信号集里面的signo信号删了

4.sigfillset

int sigfillset(sigset_t *set);

函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系
统支持的所有信号。

示例代码:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main()
{
    sigset_t tmp;
    sigemptyset(&tmp);
    sigaddset(&tmp,2);
    sigaddset(&tmp,40);
    sigprocmask(SIG_BLOCK,&tmp,NULL);
    while(1)
    {
        printf("m alive\n");
        sleep(1);
    }
    return 0;
}

把2号信号和40号信号都屏蔽了,然后再向test3发送这两个信号,发现什么事也没有发生:
【Linux】进程信号,相关函数的简单实用,linux,c++


总结

之前那篇讲共享内存的博客相对来说数据比较好,原因可能是我是读了man的使用手册以后按我理解的逻辑顺序讲的,而且我个人认为使用文档里对函数的说明比博客和百度要全面一些
有一些函数因为使用文档太长了所以我只挑了比较重要的部分来讲,如有遗漏欢迎指出
感谢支持文章来源地址https://www.toymoban.com/news/detail-798839.html

到了这里,关于【Linux】进程信号,相关函数的简单实用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux系统调用之fork,getpid,getppid函数(进程相关函数,与G老师的对话,必看!)

    如果,想要深入的学习Linux系统调用中的fork,getpid,getppid函数,还是需要去自己阅读Linux系统中的帮助文档。 具体输入命令: man 2 fork/getpid/getppid 即可查阅到完整的资料信息。 fork() 函数是 UNIX/Linux 系统中的一个系统调用 (system call),它会创建一个新的进程,称为子进程,该

    2024年02月08日
    浏览(45)
  • Linux进程信号【信号产生】

    ✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 在 Linux 中,进程具有独立性,进程在运行后可能 “放飞自我”,这是不利于管理的,于是需要一种约定俗成的方式来控制进程的运行,这就是 进程信号 ,本文将会从什么是进程信号

    2024年02月11日
    浏览(45)
  • 【Linux】第八讲:Linux进程信号详解(一)_ 认识信号 | 产生信号

    「前言」文章是关于Linux进程信号方面的知识,本文的内容是Linux进程信号第一讲,讲解会比较细,下面开始! 「归属专栏」Linux系统编程 「主页链接」个人主页 「笔者」枫叶先生(fy)  「枫叶先生有点文青病」「每篇一句」  人生天地间,忽如远行客。 ——《乐府·青青陵上

    2023年04月25日
    浏览(45)
  • Linux进程(一)信号-----信号产生

    在  Linux  中,进程具有独立性,进程在运行后可能 “放飞自我”,这是不利于管理的,于是需要一种约定俗成的方式来控制进程的运行,这就是  进程信号 ,本文将会从什么是进程信号开篇,讲述各种进程信号的产生方式及作用。 信号 是信息传递的承载方式,一种信号往

    2024年02月21日
    浏览(49)
  • Linux进程信号【信号处理】

    ✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 从信号产生到信号保存,中间经历了很多,当操作系统准备对信号进行处理时,还需要判断时机是否 “合适”,在绝大多数情况下,只有在 “合适” 的时机才能处理信号,即调用信号

    2024年02月11日
    浏览(39)
  • Linux进程信号 | 信号处理

    前面的文章中我们讲述了信号的产生与信号的保存这两个知识点,在本文中我们将继续讲述与信号处理有关的信息。 之前我们说过在收到一个信号的时候,这个信号不是立即处理的,而是要得到的一定的时间。从信号的保存中我们可以知道如果一个信号之前被block,当解除

    2024年02月09日
    浏览(41)
  • 【Linux】进程信号之信号的处理

    在前面我们讲过信号产生和保存以后,我们知道进程对于产生的信号不是立即去处理的,而是在\\\"合适\\\"的时候去处理信号, 这是因为信号的产生的异步的,当前进程可能正在做更重要的事情!。 那么信号可以被立即处理吗?答案的可以的,但是要满足这个条件: 在 Linux 中如果

    2024年02月12日
    浏览(50)
  • 【Linux】进程信号之信号的产生

    什么是信号: 信号就是一条消息,它用来通知进程系统中发生了一个某种类型的事件。 信号是多种多样的,并且一个信号对应一个事件,这样才能知道收到一个信号后,到底是一个什么事件,应该如何处理这个信号。 进程在没有收到信号时就已经知道了一个信号应该怎么被处

    2024年02月13日
    浏览(35)
  • 【Linux】进程信号之信号的保存

    实际执行信号的处理动作称为 信号递达(Delivery) 信号从产生到递达之间的状态,称为 信号未决(Pending) 。 进程可以选择阻塞 (Block )某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。 注意: 阻塞和忽略是不同的,只要信号被阻

    2024年02月13日
    浏览(39)
  • 【Linux】八、Linux进程信号详解(一)

    「前言」文章是关于Linux进程信号方面的知识,本文的内容是Linux进程信号第一讲,讲解会比较细,下面开始! 「归属专栏」Linux系统编程 「主页链接」个人主页 「笔者」枫叶先生(fy)  「枫叶先生有点文青病」「每篇一句」  人生天地间,忽如远行客。 ——《乐府·青青陵上

    2023年04月09日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包