• 信号的产生以及处理方式(一)


    /*************************************************************************************************************/
    为了理解信号,先从我们最熟悉的场景说起:
    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文件里可能包括用户password等敏感信息,不安全。

       在开发调试阶段能够用ulimit命令改变这个限制,同意产生core件。指令:#ulimit -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的实现:


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

  • 相关阅读:
    C#截取字符串的方法小结
    使用苏飞httphelper开发自动更新发布文章程序
    公务员“上班睡觉”为何会被强势围观?
    透明代理和匿名代理的区别
    Linux基础命令---ipcalc计算IP
    Linux基础命令---apwatch
    Linux基础命令---arping
    Linux基础命令---arp
    Linux基础命令---ifdown、ifup
    Linux基础命令---ifconfig
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/7202126.html
Copyright © 2020-2023  润新知