信号的产生以及处理方式

/*************************************************************************************************************/
为了理解信号 , 先从我们最熟悉的场景说起 :
1. 用户输入命令 , Shell 下启动一个前台进程。
2. 用户按下 Ctrl-C, 这个键盘输入产生一个硬件中断。
3. 如果 CPU 当前正在执行这个进程的代码 , 则该进程的用户空间代码暂停执行 ,CPU 从用 户态 切换到内核态处理硬件中断。
4. 终端驱动程序将 Ctrl-C 解释成一个 SIGINT(#2) 信号 , 记在该进程的 PCB ( 也可以说发送了 一 个 SIGINT 信号给该进程 )
5. 当某个时刻要从内核返回到该进程的用户空间代码继续执行之前 , 首先处理 PCB 中记 录的信号 , 发现有一个 SIGINT 信号待处理 , 而这个信号的默认处理动作是终止进程 , 以直接终止进程而不再返回它的用户空间代码执行。

前台进程:影响命令行工作的进程
一个命令 后面加个 & 可以放到后台运行 , 这样 Shell 不必等待进程结束就可以接受新的命令 , 启动新的进程。 Shell 可以同时运行一个前台进 程和任意多个后台进程 , 只有前台进程才能接到像 Ctrl-C 这种控 制键产生的信号。

信号相对于进程的控制流 程来说是异步的, 也就是说该进 程的用户空间代码执 行到任何地方都有可能收到 信号而终止。
/*************************************************************************************************************/
一、信号的产生方式:
       (1) 通过终端按键产生信号 (即组合键),但只能发给前台进程;
     
       (2) 硬件异常产生信号 , 调用系统函数向进程发信号, 这些条件由硬件检测到并通知内核 , 然后内核向当前进程发送适当的
                  信号。         
               (硬件异常比如: 当前进程执行了除以 0 的指令 ,CPU 的运算单元会产生异常 , 内核将这个异常解释 为 SIGFPE 信号发        
                  送给进程;  再比如:当前进程访问了非法内存地址 ,,MMU 会产生异常 , 内核 将 这个异常解释为  SIGSEGV 信号发送给
                   进程)

       (3) 由软件条件产生信号.  如 kill命令,kill 函数,raise 函数(自己给自己发送信号)     
               int kill(pid_t pid,int sig);
                返回值:成功-->ret==0;失败返回-1,error 被设置。 (附:mykill 的实现见最后...六...)
               int raise(int sig);  //自己给自己发信号
                返回值:成功-->ret==0,  失败返回非零。
                 
/*************************************************************************************************************/
二、信号的处理方式:
      (1)忽略此信号;
       (2)执行该信号的默认处理动作;
      (3)自定义该信号的处理动作(信号捕捉);  
/*************************************************************************************************************/
三、SIGQUIT与Core Dump
     SIGQUIT 的默认处理动作是终止进程并且 Core Dump,它的组合键为:Ctrl+\
      Core Dump: 当一个进程要异常终止时 , 可以选择把进程的用户空间内存数 据全部 保存到磁盘上 , 文件名通常是 core.
  core 文件的作用: 进程异常终止通常是因为有 Bug, 比如非法内存访问导致段错误 , 事后可以用调试器检查 core 文件以        
                                  查清错误原因 , 这叫做 Post-mortem Debug.
     
     默认是不允许产生 core 文件的(它的size=0) , 因为 core 文件中可能包含用户密码 等敏感信息 , 不安全。
    在开发调试阶段可以用 ulimit 命令改变这个限制 , 允许产生 core 件。指令:#uli mit -c size
   (1)改变 core 文件的大小
        
  (2)下面的代码在运行时会触发段错误,并生成 core 文件。利用该文件进行调试就会定位到错误。
                      
                        #./a.out 运行 a.out 程序(在运行时会触发段错误,并生成 core 文件:core.id)(id为进程号)
                       
                     
/*************************************************************************************************************/
四、abort函数使当前进程接收到SIGABRT信号而异常终止。
#include <stdlib.h>
void abort(void);
就像 exit 函数一样 ,abort 函数总是会成功 , 所以没有返回值。

/*************************************************************************************************************/
五、alarm函数 和SIGALRM信号。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
调用 alarm函数可以设定一个闹钟 ,也就是告诉内核在 seconds秒之后给当前进程发 SIGALRM信号 ,该信号的默认处理动作是终止当前进程。

这个函数的返回值是 0 或者是以前(它的前一次) 设定的闹钟时间还余下 的秒数
下面程序的功能:
(1)先设置闹钟时间为3s;
(2)再sleep(1)后,重新设置闹钟时间为 1s,则alarm函数的返回值为2s;
(3)count一直增加,1s后,闹钟时间到,向进程发送终止信号,进程终止。
                   
/*************************************************************************************************************/
六、自己实现 kill 函数 mykill
把a.out 程序运行起来后,在另一个终端上用  #./mykill  pid signum 终止该程序

函数main.c的代码:

函数 mykill的实现:


/*************************************************************************************************************/
      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值