10.1 引言
- 信号是软中断
- 同步:按照顺序处理事情,单线程思想。
同步的例子:
比如去餐厅吃饭,来一个客人,点一个菜,厨师做好了,在让下一个个人点菜。优缺点“速度慢,但不会出现错误。
- 异步:事情依次分配给不同线程,多线程同时处理。不论是否处理完,仍然接收其他的任务。
异步的实际例子:
比如去餐厅吃饭,来一个客人,点一个菜,下一个客人来了,继续点菜。不管厨师做好没有,这样可提高效率,让厨师一直在做菜。
异步事件的处理:1.查询法:事件发生频率高 2.通知法:事件发生事件频率低。
- 并发:
信号和线程
10.2 信号概念:
在头文件<signal.h>里面有系统定义好的一些信号类型,比如下面这些:
当程序在运行时,系统发出某个信号后,正在运行的程序收到此信号的响应动作有三种:
(1)忽略信号
(2)捕捉信号,执行用户设定的函数
(3)执行系统的默认操作
注:信号的具体含义及默认操作等,可看书具体理解,平时用掌握常见的操作即可。
10.3 函数 signal
在终端输入:man signal
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
参数: signum 就是10.2中截图中所列的那些参数
handler就是一个函数指针,代表当这个信号来了,执行handler函数
书上有如下例子:
// g++ main.cpp #include <err.h> #include <signal.h> #include <unistd.h> #include "stdio.h" static void sig_usr(int); /* one handler for both signals */ int main(void) { if (signal(SIGUSR1, sig_usr) == SIG_ERR) printf("can't catch SIGUSR1"); if (signal(SIGUSR2, sig_usr) == SIG_ERR) printf("can't catch SIGUSR2"); for (;;) pause(); // wait for signal } static void sig_usr(int signo) /* argument is signal number */ { if (signo == SIGUSR1) printf("received SIGUSR1\n"); else if (signo == SIGUSR2) printf("received SIGUSR2\n"); else printf("received signal %d\n", signo); }
#执行程序 lbw:~/lbw/gitNote$ ./a.out received SIGUSR1 received SIGUSR2 #查找PID lbw:~/lbw/gitNote$ ps -a 2727261 pts/1 00:00:00 a.out #向程序发送信号SIGUSR1和SIGUSR2 lbw:~/lbw/gitNote$ kill -10 2727261 lbw:~/lbw/gitNote$ kill -12 2727261
- 使用SIG_IGN来忽略对信号的处理:
signal(SIGUSR1, SIG_IGN); //程序收到SIGUSR1信号无任何响应动作
ctrl + c === SIGINT //终端中断符
ctrl + z === SIGQUIT
- 信号会打断阻塞的系统调用; 而被中断的调用会将errno置为 EINTR,所以可检查错误,有如下的例子来确保被信号打断的系统调能正常调用。
// 信号会打断阻塞的系统调用:为了防止出现调用open()---》signal过来了打断open()--->需要在open 失败检查加上错误检查 // EINTR代表被打断的系统调用中断 #include <errno.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char **argv) { int sfd; do { sfd = open(argv[1], O_RDONLY); if (sfd < 0) { // error check: if (errno != EINTR) { perror("open()"); exit(1); } } } while (sfd < 0); close(sfd); }