《LINUX系统编程》笔记p7
信号
常见信号
- 程序段错误
- kill 杀死进程
- Ctrl + C 结束进程
- Ctrl + Z 停止进程
kill 命令
# 查看所有的信号
kill -l
kill -<信号> pid
Linux 中全部的信号
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
UNIX 预定义的信号 (1 ~ 31),以SIG
开头
实时信号 (34 ~ 64),以SIGRT
开头.
信号默认的5种行为(man 7 signal)
- Term 默认终止进程
- Ign 默认忽略信号
- Core 默认终止进程并产生一个dump文件
- Stop 默认停止进程
- Cont 默认停止的进程继续运行
两个不能改变默认行为的信号
- SIGKILL
- SIGSTOP
前台进程组能接收的三个信号
- 中断字符
Ctrl + C
, 发出 SIGINT信号 - 退出字符
Ctrl + \
,发出 SIGQUIT信号 - 挂起字符(停止)
Ctrl + Z
发出 SIGTSTP信号
signal 函数
作用:注册新的信号处理函数,返回旧的信号处理函数。
一个信号只能有一个信号处理函数生效
#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t han‐dler);
handle 参数的取值
- SIG_IGN. 忽略信号
- SIG_DFL 信号原本缺省的操作
- SIG_ERR 报错。
信号处理函数
void sig_handle(int sig);
参数:sig 触发的信号的值。
17) SIGCHLD信号应用
子进程状态变化会触发此信号(一般是子进程退出)
使用信号回收子进程资源示例
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>void sig_wait_child(int sig) {pid_t pid;int status;pid = wait(&status);printf("收到信号:%d, pid:%d的子进程退出了\n", sig, pid);
}
int main(int argc, char * argv[]) {signal(SIGCHLD, sig_wait_child);pid_t pid;pid = fork();if (pid == 0) {sleep(10);printf("子进程:%d退出\n", getpid());return 0;}pid = fork();if (pid == 0) {sleep(15);printf("子进程:%d退出\n", getpid());return 0;}
// int status;
// pid = wait(&status);while(1) {printf("主进程在做事情...\n");sleep(30);}return 0;
}
主动发信号相关的函数
# 为指定的进程发送信号kill(2)
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);# 向当前进程发送信号raise(3)
#include <signal.h>
int raise(int sig);# 发送信号alarm(2)信号
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
// 参数: seconds 信号延迟的秒数
// 返回值:上一次信号剩余的秒数。
示例:尝试让子进程给 父进程发送 SIGKILL 信号,杀死父进程,子进程继续运行。
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>int main(int argc, char * argv[]) {pid_t pid;int ret;pid = fork();if (pid == 0) {sleep(10);ret = kill(getppid(), SIGKILL);printf("子进程 ret:%d\n", ret);sleep(20);printf("子进程退出\n");return 0;}while(1) {printf("主进程在做事情...\n");sleep(30);}return 0;
}
alarm(2)函数
作用:定时为 当前进程发送 SIGALRM 信号,实现定时器的功能。
示例代码
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>void sig_alarm_handle(int sig) {printf("时间到了:%d\n", sig);alarm(5);// 5秒钟后会收到SIGALRM信号
}
int main(int argc, char * argv[]) {signal(SIGALRM, sig_alarm_handle);alarm(5);// 5秒钟后会收到SIGALRM信号 while(1) {printf("程序运行中...\n");sleep(10);}return 0;
}
使用信号要注意的问题
- 信号处理函数应尽快返回,避免函数内死循环。
- 信号会打断程序的睡眠状态。
setitimer(2)函数
作用:实现精准定时和循环定时
#include <sys/time.h>int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
// 参数:whichITIMER_REAL: 系统的真实时钟ITIMER_VIRTUAL: 虚拟时钟,计算用户进程占用CPU 的时间。// struct itimerval {
// // 闹钟的间隔时间
// struct timeval it_interval; /* Interval for periodic timer */
// // 闹钟的启动时间
// struct timeval it_value; /* Time until next expiration */
// };
//
// struct timeval {
// time_t tv_sec; /* seconds */
// suseconds_t tv_usec; /* microseconds */
// };
示例
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>void sig_alarm_handle(int sig) {printf("时间到了:%d\n", sig);alarm(5);// 5秒钟后会收到SIGALRM信号
}
int main(int argc, char * argv[]) {signal(SIGALRM, sig_alarm_handle);// alarm(5);// 5秒钟后会收到SIGALRM信号 struct itimerval itv = {};// 5秒钟后响铃itv.it_value.tv_sec = 5;itv.it_value.tv_usec = 0;// 间隔2.5秒钟后响铃itv.it_interval.tv_sec = 2;itv.it_interval.tv_usec = 500000; // 0.5秒// 设置时间setitimer(ITIMER_REAL, &itv, NULL);while(1)pause(); // 暂停,直至有信号才解除阻塞while(1) {printf("程序运行中...\n");sleep(10);}return 0;
}