ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux编程:信号

2022-08-25 17:33:02  阅读:152  来源: 互联网

标签:set 函数 int 编程 屏蔽 信号 Linux 进程


1.信号概念

  信号是软件中断,很多比较重要的应用程序都需要信号处理。信号是一种进程之间或者内核与进程间异步通信的一种机制,例如:用户在终端键入中断键,会通过信号机制停止一个程序。

2.信号的共性

  • 简单
  • 不能携带大量信息
  • 满足某个特设条件才发送

3.信号的机制

  A给B发送信号,B 收到信号之前执行自己的代码,收到信号后,不管执行到程序的什么位置,都要暂停运行,去处理信号,处理完毕再继续执行。与硬件中断类似——异步模式。但信号是软件层面上实现的中断,早期常被称为“软中断”。
  信号的特质:由于信号是通过软件方法实现,其实现手段导致信号有很强的延时性。但对于用户来说,这个延迟时间非常短,不易察觉。

  每个进程收到的所有信号,都是由内核负责发送,内核处理

4.与信号相关的事件和状态

  产生信号:

  • 按键产生:如:Ctrl+c、Ctrl+z、Ctrl+\
  • 系统调用产生:如:kill、raise、abort
  • 软件条件产生:如:定时器 alarm
  • 硬件异常产生:如:非法访问内存(段错误)、除 0(浮点数例外)、内存对齐出错(总线错误)
  • 命令产生:如:kill命令

  递达:递送并且到达进程。

  未决:产生和递达之间的状态。主要由于阻塞(屏蔽)导致该状态。

  信号的处理方式:

  • 执行默认动作(每一个信号都有默认的处理事件)
  • 忽略
  • 捕捉(调用户处理函数 )

  linux内核的进程控制块PCB是一个结构体,包含了信号相关信息,主要指阻塞信号集和未决信号集。

  阻塞信号集:将某系信号加入集合,对他们设置屏蔽,当屏蔽x信号后,在收到该信号,该信号的处理将推后(解除屏蔽后)

  未决信号集:信号产生,未决信号集中该信号位立刻反转1,表示信号处于未决状态。当信号被处理对应位反转为0.这一刻往往非长短暂。

5.信号四要素

  在信号使用之前,要确定其四要素

  编号、名称、事件、默认处理动作

6.信号的产生

  • 终端按键产生信号
  • 硬件异常产生信号
  • kill函数/命令产生信号
    • 函数原型
      1 int kill(pid_t pid, int sig);  //成功:0;失败:-1,设置errno
      2 //sig:不推荐直接使用数字,应使用宏名,因为不同操作系统信号编号可能不同,但名称一致
      3 //pid > 0: 发送信号给指定的进程
      4 //pid = 0: 发送信号给 与调用 kill 函数进程属于同一进程组的所有进程。
      5 //pid < 0: 取|pid|发给对应进程组。
      6 //pid = -1:发送给进程有权限发送的系统中所有进程

       

    • kill命令产生信号:kill -SIGKILL pid
  • 软件条件产生信号
    • alarm函数 : 设置定时清。指定seconds后,内核会给当前进程发送SIGALRM信号,进程收到该信号,默认动作中止,每个进程都有且只有一个唯一定时器。
    • 1 unsigned int alarm(unsigned int seconds);    //返回 0 或剩余的秒数,无失败。
    • 使用time命令查看程序执行的时间 
      • time ./test
      • 实际执行时间=系统时间+用户时间+等待时间
      • time ./test > out
      • 结论:程序运行的瓶颈在于IO,优化程序,首选优化IO 
    • setitimer函数原型:设置定时器。可替代alarm函数。精度微秒,可以实现周期定时
    • 1 int setitimer (int which, const struct itimerval *new_value, struct itimerval *old_value);    //成功:0;失败:-1,设置errno
      //which:指定定时方式(①自然定时:ITIMER_REAL)(②虚拟空间计时(用户空间)ITIMER_VIRTUAL)(③运行时计时(用户+内核):ITIMER_PROF
      //参数二:结构体设置间隔时间和单次时间
      //参数三:返回旧闹钟的剩余时间(传出参数)
      //it_value:结构体内部的参数:第一次触发信号的时间
      //it_interval:结构体内部的参数:用来设定两次定时任务之间间隔的时间(第二次和第一次 or 第三次和第二次之间的时间间隔)

 7.信号集操作函数+原理(重)

    控制原理:内核通过读取未决信号集来判断信号是否应被处理。信号屏蔽字mask可以影响未决信号集。而我们可以再应用程序中自定义set来改变mask。以达到屏蔽指定信号的目的。(重点) 

  

 

    sigprocmask函数

      作用:用来屏蔽信号、解除屏蔽也是用该函数。其本质,读取或修改进程的信号屏蔽字(PCB中)

      

1 int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);   //成功:0;失败:-1,设置 errno
2 //set:传入参数,是一个位图,set 中哪位置 1,就表示当前进程屏蔽哪个信号。
3 //oldset:传出参数,保存旧的信号屏蔽集
4 //how 参数取值: 假设当前的信号屏蔽字为 mask
5 //SIG_BLOCK: 该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。set包含了我们希望阻塞的附加信号。
6 //SIG_UNBLOCK: 该进程新的信号屏蔽字是其当前信号屏蔽字和set所指向信号集的补集的交集。set包含了我们希望解除阻塞的信号.
7 //SIG_SETMASK: 自定义set替换mask(mask表示系统自带的阻塞信号集)

    sigpending函数

      作用:读取当前进程的未决信号集

      

1 int sigpending(sigset_t *set);    //set 传出参数。 返回值:成功:0;失败:-1,设置 errno

8.信号捕捉

signal函数

  作用:注册一个信号捕捉函数(注册而非创建)

  原型:

1 sighandler_t signal(int signum, sighandler_t handler);
2 typedef void (*sighandler_t)(int);//函数指针类型 需要注意的就是需要传入一个整形参数 不管用不用

sigaction函数

  作用:修改信号处理动作(通常在Linux用来注册一个信号的捕捉函数)

  原型:

1 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
2 //act: 传入参数、新的处理方式
3 //oldact:  传出参数,旧的处理方式  

 9.信号捕捉特性(重)

  • 进程正常运行时,默认PCB中有一个信号屏蔽字,假定为✳,它决定了进程自动屏蔽那些信号。当注册了某个信号捕捉函数,捕捉到该信号后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由✳来指定。而是用sa_mask来指定。调用完信号处理函数,在恢复为✳。
  • xxx信号捕捉函数执行期间,xxx信号自动被屏蔽
  • 阻塞的常规信号不支持排队、产生多次只记录一次。

10.内核实现信号捕捉过程

  

 

 11.SIGCHLD信号

  产生条件:

      子进程中止时

      子进程接收到SIGSTOP信号停止时

      子进程处在停止态,接收到SIGCONT后唤醒时

  借助该信号回收进程:

    子进程结束运行,其父进程会收到 SIGCHLD 信号。该信号的默认处理动作是忽略。可以捕捉该信号,在捕捉函数中完成子进程状态的回收。

标签:set,函数,int,编程,屏蔽,信号,Linux,进程
来源: https://www.cnblogs.com/chen-zj/p/16624994.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有