Linux系统编程--信号量

107 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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)

image.png

二、中断系统调用

系统调用可分为两类:慢速系统调用和其他系统调用。

  1. 慢速系统调用:可能会使进程永远阻塞的一类。如果在阻塞期间收到一个信号,该系统调用就被中断, 不再 继续执行 ( 早期 ) ;也可以设定系统调用是否重启。如, read 、 write 、 pause 、 wait...

  2. 其他系统调用: getpid 、 getppid 、 fork...

  3. 结合 pause ,回顾慢速系统调用: 慢速系统调用被中断的相关行为,实际上就是 pause 的行为: 如, read

    • 想中断 pause ,信号不能被屏蔽。

    • 信号的处理方式必须是捕捉 ( 默认、忽略都不可以 )

    • 中断后返回 -1 , 设置 errno 为 EINTR( 表“被信号中断” ) 可修改 sa_flags 参数来设置被信号中断后系统调用是否重启。 SA_INTERRURT 不重启。 SA_RESTART 重启。

    • sa_flags 还有很多可选参数,适用于不同情况。如:捕捉到信号后,在执行捕捉函数期间,不希望自动阻塞该 信号,可将 sa_flags 设置为 SA_NODEFER ,除非 sa_mask 中包含该信号。

三、信号注意问题

  1. 子进程继承父进程的信号屏蔽字和信号处理动作,但子进程没有继承未决信号集

  2. 注意注册信号捕捉函数的位置。

  3. 应该在 fork 之前,阻塞 SIGCHLD 信号。注册完捕捉函数后解除阻塞。