linux操作系统之信号

(1)信号的概念

           信号的特点:简单,不能携带大量信息,满足某种特定条件才触发。

           信号的机制;“软中断”,通过软件方式实现,具有很强的延时性。每个进程收到的信号,都由内核负责发送,内核处理

           信号的产生:1)按键产生(ctrl+c,ctrl+z,ctrl+\)

                                   2) 系统调用产生(kill,abort,raise)

                                   3)软件条件产生(定时器alarm)

                                   4)硬件异常产生((非法访问内存)段错误,(除0)浮点数例外,内存对齐出错(总线错误))

                                   5)命令产生(kill)

         信号的处理方式:1)执行默认动作

                                                        1>Term :终止进程  2>lgn:忽略信号3>core:终止进程(查验死亡原因,gdb调试)

                                                        4>Stop:停止(暂停)进程5>Cont:继续进程

                                         2)忽略(舍弃)

                                       3)捕捉(掉用户处理函数)

         信号的四要素:编号  名称  事件 默认处理动作

        Linux内核中有一个PCB进程控制块,是一个结构体,task_struct,里面保存了进程id,状态,工作目录,用户id,用户组id,文件描述符和阻塞信号集及未决信号集。

       信号的编号:由kill -i查看当前系统可使用的命令,其中1~31为常规信号,34~64为实时信号。

       在31个常规信号中,9)SIGKILL和19)SIGSTOP信号不能被忽略和捕捉,智能执行默认动作,不能设置其为阻塞。

(2)信号的产生

     1)终端按键产生信号:ctrl+c  -->2)SIGINT(终止、中断)ctrl+z --->20)SIGTSTP(暂时、停止)  ctrl+\--->3)SIGQUIT(退出)

     2) 硬件产生信号:除零操作-->8)SIGFPE(浮点数例外)     非法访问内存-->11)SIGSEGV(段错误)   总线错误 --->7)SIGBUS

     3) kill函数或命令产生信号: kill -SIGKILL pid

              int kill(pid_t pid,int sig);      成功:0 失败-1

                                   sig:不推荐直接使用数字,应使用宏名。因为不同的操作系统可能编号不一样,但名称一致。

                pid>0   发送信号给指定进程

                pid<0    发送信号给调用kill函数同一进程组的所有进程。

               pid<0     取|pid|发给对应进程组

               pid=-1    发送给当前用户组的所有进程                 

           raise函数:给自己发指定信号  int raise(int sig)==kill(getpid(),sig)

          abort函数:给自己发送异常终止信号  6)SIGABRT信号,终止并产生core文件,void abort(void)

    4)软件产生信号

             alarm函数:定时固定秒数之后,内核给当前进程发送14)SIGALRM信号,终止进程(每个进程只有一个闹钟)   

             unsigned int alarm(unsigned int seconds);  返回0或剩余的秒数(上一次定时剩余的秒数) alarm(0)取消定时

                        采用自然定时发,与进程状态无关

            setitimer函数:定时可以达到微秒,可实现循环定时。

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

                     参数which(定时方式):ITIMER_REAL(自然定时法-)-->14)SIGLARM

                                                                   ITIMER_VIRTUAL(虚拟空间计时,用户时间)---->26)SIGVTALRM

                                                                  ITMER_PROF(运行时间计时,用户+内核)------>27)SIGPROF

                   程序实际执行的时间=系统时间+用户时间+等待时间

                  

            其中it_interval为周期定时的时间,it_value为当前定时的时间。

(3)信号集操作函数

      内核通过读取未决信号集来判断信号是否被处理,信号屏蔽字(阻塞信号集)mask可以影响未决信号集。            

           1 )信号集设定

               

        2)sigprocmask函数:屏蔽信号,接触屏蔽,设置信号集

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

                          how:SIG_BLOCK,set表示需要屏蔽的信号

                                   SIG_UNBLOCK,set表示需要解屏蔽的信号

                                   SIG_SETMASK:set表示需要替代原始的新屏蔽集。

        3)sigpending函数:获取当前的未决信号集

                  int sigpending(sigset_t*set);    //使用sigsimember来判断某个信号是否在其中

(4)信号捕捉

           1)signal函数:注册一个信号捕捉函数,抓信号由内核进行

                      typedef void(*sighandler_t)(int);

                     sighandler_t signal(int signum,sighandler_t handler);

                                     参数:signum(捕捉的信号)  handle(处理的函数)

         2)sigaction函数:修改信号处理动作

                    int sigaction(int signum,const struct sigaction*act,struct sigaction*oldact)

              

              重点掌握:1>sa_handler:指定的信号捕捉后的处理函数名,可以赋值为SIG_IGN(表示忽略)SIG_DFL(表示执行默认)

                              2>sa_mask:调用信号处理函数时使用的屏蔽信号集(临时设置,执行完函数即失效)(如果有信号为非屏蔽                                                           信号集中的信号,会先处理该信号)

                               3>sa_flags:设置为0,表默认属性(信号捕捉函数期间,默认屏蔽本信号)

                               阻塞的常规信号不支持排队,产生多次只记录一次,捕捉函数执行完之后再执行该阻塞信号。

             其他:第五个信号舍弃不用

                        当sa_flags==SA_SIGINFO时,使用第二个参数处理程序。

            3)内核实现信号捕获过程

                    

猜你喜欢

转载自blog.csdn.net/xx18030637774/article/details/82225811