按下 Ctrl + C 后,命令行中的前台进程会被终止。为什么???
信号是一种 "软件中断",用来处理异步事件
信号是一种类型的进程间通信方式 (一个进程向另一个进程发送信号)
硬件异常
终端信号
软件信号
SIGINT ( Ctrl + C )
SIGQUIT ( Ctrl + \ )
SIGTSTP ( Ctrl + Z )
子进程退出:父进程收到 SIGCHLD 信号
父进程退出:子进程可能收到信号 (什么信号?)
定时器到期:alarm(),ualarm(),timer_create(),...
主动发信号:kill(),raise(),...
System V
BSD
#include
#include
typedef void(*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
sighandler_t sysv_signal(int signum, sighandler_t handler);
sighandler_t bsd_signal(int signum, sighandler_t handler);
#include
#include
int kill(pid_t pid, int sig); // pid > 0, pid == 0, pid < -1
int raise(int sig); // 信号处理完毕才返回
kill 函数当 pid > 0 时,将信号发给指定进程;当 pid == 0 时,将信号发送到当前的进程组中;当 pid < -1 时,将信号发送给指定的进程组中
raise 函数将信号发送给当前进程
main.c
- // #define _GNU_SOURCE
- // #define _XOPEN_SOURCE 600
- // #define _POSIX_C_SOURCE 200800L
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <signal.h>
-
- void signal_handler(int sig)
- {
- printf("handler : sig = %d\n", sig);
- }
-
- int main(void)
- {
- signal(SIGINT, signal_handler);
- signal(40, signal_handler);
- // sysv_signal(SIGINT, signal_handler);
- // bsd_signal(SIGINT, signal_handler);
-
- while( 1 )
- {
- sleep(1);
- }
-
- return 0;
- }
-
第 19 行和第 20 行,我们为 SIGINT 信号和 信号值为 40 的信号,注册信号处理函数,信号处理函数为 signal_handler
第 20 行和第 21 行被注释掉的 sysv_signal 函数和 bsd_signal 函数的作用在这边的和 signal 函数的作用是一样的,都是在 SIGINT 信号或信号值为 40 的信号触发时,调用 signal_handler 函数
程序运行结果如下图所示:
我们键入 Ctrl + C时 内核会发送 SIGINT 信号给当前前台进程组的进程,SIGINT 信号的默认行为是终止进程的运行,由于在这里我们为 SIGINT 信号注册了信号处理函数,所以会调用到 signal_handler 函数打印 SIGINT 的信号值,最后我们键入 Ctrl + \,内核会发送 SIGQUIT 信号给当前前台进程组的进程,SIGQUIT 信号的默认行为也是终止进程的运行,由于我们没有改变 SIGQUIT 信号的处理行为,所以 a.out 进程就被终止运行了
test.c
- #include
- #include
- #include
- #include
- #include
-
-
- int main(int argc, char* argv[])
- {
- int pid = atoi(argv[1]);
- int sig = atoi(argv[2]);
-
- printf("send sig(%d) to process(%d)...\n", sig, pid);
-
- kill(pid, sig);
-
- raise(SIGINT);
-
- while( 1 )
- {
- printf("while...\n");
- sleep(1);
- }
-
- return 0;
- }
第 15 行,使用 kill 函数向指定进程发送指定信号
第 17 行,使用 raise 函数向自身发送 SIGINT 信号
程序运行结果如下图所示
test.out 执行后向 a.out 进程发送信号值为 40 的信号,然后给自己发送 SIGINT 信号终止了运行,a.out 进程收到信号值为 40 的信号后,由于注册了对应的信号函数,会调用 signal_handler 这个信号处理函数,打印出来的信号值为 40,是 test.out 发送过来的信号
三种自定义信号处理函数有什么区别???