开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情。
一、信号量
应用于线程、进程间同步。
相当于初始化值为 N 的互斥量。 N值,表示可以同时访问共享数据区的线程数。
函数:
sem_t sem; 定义类型。
int sem_init(sem_t *sem, int pshared, unsigned int value);
-
参数:
sem: 信号量
pshared:
-
0: 用于线程间同步
-
1: 用于进程间同步
value:N值。(指定同时访问的线程数)
-
sem_destroy();
sem_wait(); 一次调用,做一次-- 操作,当信号量的值为 0 时,再次 -- 就会阻塞。(对比 pthread_mutex_lock)
sem_post(); 一次调用,做一次++ 操作,当信号量的值为 N 时, 再次 ++ 就会阻塞。(对比 pthread_mutex_unlock)
二、中断系统调用
系统调用可分为两类:慢速系统调用和其他系统调用。
-
慢速系统调用:可能会使进程永远阻塞的一类。如果在阻塞期间收到一个信号,该系统调用就被中断, 不再 继续执行 ( 早期 ) ;也可以设定系统调用是否重启。如, read 、 write 、 pause 、 wait...
-
其他系统调用: getpid 、 getppid 、 fork...
-
结合 pause ,回顾慢速系统调用: 慢速系统调用被中断的相关行为,实际上就是 pause 的行为: 如, read
-
想中断 pause ,信号不能被屏蔽。
-
信号的处理方式必须是捕捉 ( 默认、忽略都不可以 )
-
中断后返回 -1 , 设置 errno 为 EINTR( 表“被信号中断” ) 可修改 sa_flags 参数来设置被信号中断后系统调用是否重启。 SA_INTERRURT 不重启。 SA_RESTART 重启。
-
sa_flags 还有很多可选参数,适用于不同情况。如:捕捉到信号后,在执行捕捉函数期间,不希望自动阻塞该 信号,可将 sa_flags 设置为 SA_NODEFER ,除非 sa_mask 中包含该信号。
-
三、信号注意问题
-
子进程继承父进程的信号屏蔽字和信号处理动作,但子进程没有继承未决信号集
-
注意注册信号捕捉函数的位置。
-
应该在 fork 之前,阻塞 SIGCHLD 信号。注册完捕捉函数后解除阻塞。