信号初体验:
1.信号通信的理解
内核中有通信对象,前边通信对象是管道,这里是信号。
如果进程1想与进程2通过信号通信,不能通过用户空间,它必须先告诉内核,让内核告诉进程2 如图所示:
2.信号的含义:
下面看内核空间有多少种信号 可以通过kill 加个选项-l 可以看到内核总共可以发送64种信号:数字代表信号的ID 后边的宏代表他的功能,每个信号都有他的意义。
查看每个信号的含义:
man 7 signal
SIGINT ctrl+c 发出的信号
SIGQUIT ctrl+\ 终止程序 产生内存映像文件
SIGILL 非法指令
SIGABRT 通过abort函数实现程序终止
SIGFPE 除数为0 就会产生这个信号 叫浮点异常
SIGKILL 必杀信号
SIGSEGV 段错误
SIGPIPE 管道破裂
SIGALRM alarm是闹钟信号,用alarm()函数设置闹钟,告诉系统时间到了,就会发送
SIGTERM 终止信号 kill命令就是向进程发这个的信号
SIGCHLD 子进程终止或停止的时候 会向父进程发此信号
SIGCONT 让一个暂停的进程继续
SIGSTOP 让一个进程暂停
SIGTSTP 按下CTRL+Z
3.关于信号的发送存在这两个个问题
a.内核中很多信号,比如进程1发送信号给进程2,用户空间发送不了,用户空间不具备发送信号的能力;进程1想让内核发送信号给进程2,必须告诉内核要发什么信号,信号的编号是什么。
b.用户空间有很多进程,对于内核来讲,到底给哪个进程发送信号?所以进程1要告诉内核发信号给应用层的哪个进程。
因此发送信号给指定进程需要两个参数:信号的编号和进程的编号。
4.实战深入理解
之前学过linux命令kill, kill 9 pid可以杀死指定进程,9就是编号为9的信号,我们写个程序完成之前的kill 9操作。
第一步:先写个”求死”进程。
linux@ubuntu:~$ vim test.c
linux@ubuntu:~$ gcc test.c
通过kill命令进入内核,kill命令其实也是应用程序。kill函数是系统调用函数,告诉内核发送9号信号;第二个选项是发送pid,告诉内核,发给test.c进程,test.c进程就会收到这个信号。
这里我们总结下 kill函数的形式:
kill(pid_t pid,int sig)
pid:整数,要接收信号的进程的进程号
0 信号被发送到所有和pid进程在同一个进程组的进程
-1 信号发送给所有的进程表中的进程(除了进程号大的进程外)
sig:信号编号
第二步:使用快捷键 CTRL+ALT+T 再打开一个终端 写个kill函数,实现kill命令功能。
linux@ubuntu:~$ vim kill.c
linux@ubuntu:~$ gcc kill.c -o kill
linux@ubuntu:~$ ./kill 9 4245
切换终端 观察之前的test.c进程
进程4245,也就是test.c进程已经被killed,实现的过程为kill.c进程发送信号给内核
内核收到信号9及进程编号4245后 发信号给4245,进程4245响应信号,执行默认的信号处理方式,即杀死进程。