信号共性:
简单、不能携带大量信息、满足条件才发送
信号的特质:
信号是软件层面的 中断。一旦信号产生,无论程序执行到什么位置,必须停止运行,处理信号,处理结束,再继续执行后续指令。
所有信号的产生及处理都是 由 内核完成的。
信号相关概念:
产生信号:
1.按键产生 如:ctrl+c
2.系统调用产生 如:kill
3.软件条件产生 如:定时器 alarm
4.硬件异常产生 如:非法访问内存(段错误)、除0
5.命令产生 如:kill命令
概念:
未决:产生与递达之间状态
递达:产生并且送达到进程、直接被内核处理掉
信号处理方式:执行默认处理动作(终止进程、忽略信号、暂停进程、继续运行、终止生成core文件查看进程死亡原因)
、忽略、捕捉(自定义)
阻塞信号集(信号屏蔽字):本质:位图。用来记录信号的屏蔽状态。一旦被屏蔽的信号,在解除屏蔽前,一直处于未决状态。
未决信号集: 本质:位图。用来记录信号的处理状态。该信号集中的信号表示,已经产生,但尚未被处理。
可以操作阻塞信号集 来影响未决信号集 未决信号集不允许操作
信号四要素:
信号使用之前,应先确定四要素,然后再用
信号编号、信号名称、信号对应事件、信号默认处理动作
kill命令和kill函数:
kill -9 -1900 (刹死 进程组号为 1900 的所有进程 进程组号同父进程号)
int kill(pid_t pid,int signum)
参数:
pid: >0:发送信号给指定进程
=0:发送信号给 跟调用kill函数的那个进程处于同一进程组的进程
<-1:取绝对值,发送信号给该绝对值所对应的进程组的所有组员
=-1:发送信号给,有权限发送的所有进程
返回值:
成功:0
失败:-1 errno
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main(){
pid_t pid = fork();
if(pid>0){
while(1){
printf("parent,pid=%d\n",getpid());
sleep(1);
}
}else if(pid==0){
printf("child ,pid= %d,ppid=%d\n",getpid(),getppid());
sleep(10);
kill(0,SIGKILL);
}
return 0;
}
alarm 函数:
每个进程有且只有唯一 一个定时器
定时发送SIGALRM 给当前进程。
unsigned int alarm(unsigned int seconds);
seconds:定时秒数
返回值:上次定时剩余时间
无错误现象
alarm(0)取消闹钟
time 命令 :查看程序执行时间。 实际时间 = 用户时间+内核时间+等待时间 --》优化瓶颈 IO
//测试一秒 数数
#include<stdio.h>
#include<unistd.h>
int main(){
int i;
alarm(1);
for(i=0;;i++){
printf("%d\n",i);
}
return 0;
}
setitimer函数:
int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
参数:
which: ITIMER_REAL: 采用自然计时 --》 SIGALRM
ITIMER_VIRTUAL: 采用用户计时 --》SIGVTALRM
ITIMER_PROF : 采用内核 +用户空间计时 --》SIGPROF
new_value:定数秒数
类型: struct itimerval{
struct timeval{
time_t tv_sec;
suseconds_t tv_usec;
}it_interval;
struct timeval{
time_t tv_sec;
suseconds_t tv_usec;
}it_value;
}
old_value:传出参数,上次定时剩余时间。
e.g:
struct timeval ner_t;
struct timeval old_t;
new_t.it_interval.tv_sec=1;
new_t.it_interval.tv_usec=0;
new_t.it_value.tv_sec=0;
new_t.it_value.tv_usec=0;
setitimer(&new_t,&old_t)
返回值:
成功:0
失败:-1 errno
其他几个发信号函数:
int raise(int sig)
void abort(void)