linux下的信号就是我们看到信息的一种,比如在现实生活中我们在过马路的时候我们看到红灯(红灯就是信号),会停下来(信号的识别,看到信号并直到怎么做);回到linux操作系统下,我们写的代码中有无限循环语句时,进程一直在执行不会结束,在键盘上按ctrl+c键,操作系统给进程发送一个2号信号来结束进程。操作系统给进程发信号,其实就是设置该进程PCB中的信号字段(当一个进程收到一个信号时,不会立即去处理,而是等到合适的时候处理)。
用kill -l 命令查看系统的信号列表,如下图(1-31普通信号,34-62实时信号):
上述中的ctrl+c产生的信号只能发送给前台进程,shell可以同时运行一个前台进程和任意多个后台进程,一个命令后面加个&就可以放到后台运行;
#include<stdio.h>
int main()
{
while(1)
;
return 0;
}
在mysignal进程运行时查看进程信息,R+表示该进程是前台进程;
当我们在执行./mysignal时在其后面加上&就可以变为后台进程:
变为后台进程后,在后台执行mysignal进程时,ls命令也可以执行,由R+变为了R;
信号的处理:
1.忽略此信号
2.执行该信号的默认动作
3.提供一个信号处理函数,自定义其动作(信号的捕捉)
前两个都很简单,主要看看第三个捕捉信号:
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
void myhandler(int sig)
{
printf("pid:%d,sig:%d\n",getpid(),sig);
}
int main()
{
int i = 0;
for(i = 1; i < 32; i++)
{
signal(i,myhandler);
}
while(1)
;
return 0;
}
信号的产生:
1.通过终端按键产生信号
ctrl+z,ctrl+c等等...
2.调用系统函数产生信号
kill函数,向pid进程发送sig信号;
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
kill(atoi(argv[1]),atoi(argv[2]));
printf("pid:%d,sig%d,kill successed\n",atoi(argv[1]),atoi(argv[2]));
return 0;
}
先运行一个进程mysignal,调用kill函数给该进程发信号结束这个进程;
raise函数:自己给自己发信号
#include <signal.h>
int raise(int sig);
在6秒后自己给自己发送9号信号,结束自己;
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
int main()
{
int i = 0;
while(1)
{
printf("waitting..%d\n",6-i);
sleep(1);
if(i++ > 5)
raise(9);
}
return 0;
}
abort:函数使当前进程接收到信号而异常终止;
3.由软件条件产生信号
alarm(unsigned int seconds)
这个函数可以设定一个闹钟,告诉内核在seconds秒之后给当前进程发送SIGALRM信号。该信号的默认处理动作是终止当前进程;