(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)内核实现信号捕获过程