linux线程同步05

线程信号:
线程是一种轻量级的进程,因此进程的信号同样适用于线程。不过相对于进程信号,线程拥有与信号相关的私有数据——线程信号掩码,则就决定了线程在信号操作时具有以下特性:
A】每个线程可以先别的线程发送信号,pthread_kill()函数用来完成这一操作。
B】每个线程都可以设置自己的阻塞集合。pthread_sigmask()用来完成这一操作。类似于进程中的sigprocmask()函数。主进程创建出来的线程继承主进程的掩码。
C】每个线程需要设置针对某信号的处理方式,但同一个进程中对某信号的处理方式只能有一个有效,即最后一次设置的处理方式。即在所有的线程里,同一信号在任何线程里的对该信号的处理一定相同
D】如果别的进程向当前进程发来一个信号,具体由哪个形成去处理,是未知的。

1、 向指定的线程发送信号:pthread_kill()
A】函数原型:extern  int  pthread_kill(pthread_t  __threadid,int  __signo)
B】参数说明:threadid是目标线程,sigo是要发送的信号。pthread_kill()函数用于请求将信号传送给线程,调用进程中,信号将被异步定向到线程。如果signo为0,就会进行错误检查而不发送信号。成功完成后,pthread_kill()将返回0。否则会返回一个错误编号,用于指明错误(未设置errno变量)。
2、 调用线程的信号掩码:pthread_sigmask()
A】函数原型:extern  int  pthread_sigmask(int  __how,__const  __sigset_t  *restrict   __newmask, __sigset_t  *restrict   __oldmask);
B】说明:函数类似于进程信号中的sigprocmask()函数。pthread_sigmask()用来检查或更改线程的信号掩码。(此部分可参考进程和进程通信  信号部分内容)。
C】参数:第一个参数how定义如何更改调用线程的信号掩码。其合法值有以下三个(此小点内容与sigprocmask()重复)
#define  SIG_BLOCK  0
#define  SIG_UNBLOCK    1
#define   SIG_SETMASK 2
宏说明:
SIG_BLOCK:将第2个参数所描述的集合添加到当前进程阻塞的信号集中。
SIG_UNBLOCK:将第2个参数所描述的集合从当前进程阻塞信号集中删除。
SIG_SETMASK:不管之前的阻塞信号,仅设置当前的进程阻塞的集合为第2个参数描述的对象。
如果newmask值是个空指针,则参数how没有意义,且不会更改线程的阻塞信号集,因此该调用可以用于查询当前受阻塞的信号。
D】返回:执行成功后,返回0,失败后返回错误编号来指明错误(未设置errno变量),另外,如果由于某种原因pthread_sigmask()失败,那么线程的信号掩码将不会变化。


sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。

他是POSIX的信号接口,而signal()是标准C的信号接口(如果程序必须在非POSIX系统上运行,那么就应该使用这个接口)

给信号signum设置新的信号处理函数act, 同时保留该信号原有的信号处理函数oldact

int sigaction(int signo,const struct sigaction *restrict act,

              struct sigaction *restrict oact);

结构sigaction定义如下:

struct sigaction{
  void (*sa_handler)(int);
   sigset_t sa_mask;
  int sa_flag;
  void (*sa_sigaction)(int,siginfo_t *,void *);
};

sa_handler字段包含一个信号捕捉函数的地址

sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

 sa_flags 成员用于指定信号处理的行为,它可以是一下值的“按位或”组合。
 
 ◆ SA_RESTART:使被信号打断的系统调用自动重新发起。
 ◆ SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
 ◆ SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵

尸进程。
 ◆ SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
 ◆ SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
 ◆ SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。

 re_restorer 成员则是一个已经废弃的数据域,不要使用。

(3)    如果不需要重置该给定信号的处理函数为缺省值;并且不需要阻塞该给定信号(无须设置sa_flags标志),那么必须将sa_flags清零,否则运行将会产生段错误。但是sa_flags清零后可能会造成信号丢失!


如果参数oldact不是NULL指针,则原来的信号处理方式会由此结构sigaction返回

------------------------------------我是分割线-----------------------------------

(1)    创建信号集函数

    创建信号集函数有如下5个:

①    sigemptyset:初始化信号集合为空。

②    sigfillset:把所有信号加入到集合中,信号集中将包含Linux支持的64种信号。

③    sigaddset:将指定信号加入到信号集合中去。

④    sigdelset:将指定信号从信号集中删去。

⑤    sigismember:查询指定信号是否在信号集合之中。

  设置信号屏蔽位函数

每个进程都有一个用来描述哪些信号递送到进程时将被阻塞的信号集,该信号集中的所有信号在递送到进程后都将被阻塞。调用函数sigprocmask可设定信号集内的信号阻塞或不阻塞。

函数原型

int sigprocmask(int how,const sigset_t *set,sigset_t *oset)

how(决定函数的操作方式)

SIG_BLOCK:增加一个信号集合到当前进程的阻塞集合之中

SIG_UNBLOCK:从当前的阻塞集合之中删除一个信号集合

SIG_SETMASK:将当前的信号集合设置为信号阻塞集合


最后一个参数是进程原来的信号集。如果你只需要改变信号的阻塞情况而不需要关心原来的值,可以传递NULL指针给函数。如果你希望什么也不改变,只是想获得当前信号掩码的信息,那么把set设置成NULL,old中返回当前的设置。

------------------------------------我是分割线--------------------------------------

信号的阻塞就是让系统暂时保留信号留待以后发送。(注意:不是发送,而是延迟发送)一般情况下信号的阻塞只是暂时的,只是为了防止信号打断敏感的操作。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值