sigsuspend sigprocmask函数的使用方法

一个进程的信号屏蔽字规定了当前阻塞而不能递送给该进程的信号集调用函数sigprocmask可以检测或更改其信号屏蔽字,或者在一个步骤中同时执行这两个操作。

#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
返回值:若成功则返回0,若出错则返回-1

首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回。

其次,若set是一个非空指针,则参数how指示如何修改当前信号屏蔽字。

表10-4说明了how可选用的值。注意,不能阻塞SIGKILL和SIGSTOP信号

表10-4 用sigprocmask更改当前信号屏蔽字的方法


  how


  说明

  SIG_BLOCK   该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。set包含了我们希望阻塞的附加信号
  SIG_UNBLOCK   该进程新的信号屏蔽字是其当前信号屏蔽字和set所指向信号集补集的交集。set包含了我希望解除阻塞的信号
  SIG_SETMASK   该进程新的信号屏蔽字将被set指向的信号集的值代替

如果set是空指针,则不改变该进程的信号屏蔽字,how的值也无意义

在调用sigprocmask后如果有任何未决的、不再阻塞的信号,则在sigprocmask返回前,至少会将其中一个信号递送给该进程。

1、有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数。这种情况是通过阻塞信号实现的。

2、信号阻塞和忽略信号的区别。

阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。

1)头文件:#include <signal.h>

2)一个保护临界区代码的错误实例:(sigprocmask()和pause()实现)

#include <unistd.h>

#include <signal.h>

#include <stdio.h>

void handler(intsig)   //信号处理函数的实现

{

printf("SIGINT sig");

}

int main()

{

sigset_tnew,old;

structsigaction act;

act.sa_handler = handler;  //信号处理函数handler

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

sigaction(SIGINT, &act, 0); //准备捕捉SIGINT信号

sigemptyset(&new);

sigaddset(&new, SIGINT);

sigprocmask(SIG_BLOCK, &new,&old); //将SIGINT信号阻塞,同时保存当前信号集

printf("Blocked");

sigprocmask(SIG_SETMASK, &old,NULL);  //取消阻塞

pause();

return0;

}

上面实例的问题是:本来期望pause()之后,来SIGINT信号,可以结束程序;可是,如果当“取消阻塞”和“pause”之间,正好来了SIGINT信号,结果程序因为pause的原因会一直挂起。。。

解决的方式,当然是sigsuspend()函数了。

3)使用sigsuspend()的程序

#include <unistd.h>

#include <signal.h>

#include <stdio.h>

void handler(int sig)  //信号处理程序

{

if(sig == SIGINT)

printf("SIGINT sig");

else if(sig == SIGQUIT)

printf("SIGQUIT sig");

else

printf("SIGUSR1 sig");

}

int main()

{

sigset_tnew,old,wait;   //三个信号集

structsigaction act;

act.sa_handler = handler;

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

sigaction(SIGINT, &act,0);   //可以捕捉以下三个信号:SIGINT/SIGQUIT/SIGUSR1

sigaction(SIGQUIT, &act, 0);

sigaction(SIGUSR1, &act, 0);

sigemptyset(&new);

sigaddset(&new,SIGINT);  //SIGINT信号加入到new信号集中

sigemptyset(&wait);

sigaddset(&wait, SIGUSR1); //SIGUSR1信号加入wait

sigprocmask(SIG_BLOCK, &new,&old);      //将SIGINT阻塞,保存当前信号集到old中

//临界区代码执行

if(sigsuspend(&wait) != -1) //程序在此处挂起;用wait信号集替换new信号集。即:过来SIGUSR1信 号,阻塞掉,程序继续挂起;过来其他信号,例如SIGINT,则会唤醒程序。执行sigsuspend的原子操作。注意:如果“sigaddset(&wait,SIGUSR1);”这句没有,则此处不会阻塞任何信号,即过来任何信号均会唤醒程序。

printf("sigsuspend error");

printf("Aftersigsuspend");

sigprocmask(SIG_SETMASK, &old, NULL);

return0;

}

sigsuspend的原子操作是:

(1)设置新的mask阻塞当前进程(上面是用wait替换new,即阻塞SIGUSR1信号)

(2)收到SIGUSR1信号,阻塞,程序继续挂起;收到其他信号,恢复原先的mask(即包含SIGINT信号的)。

(3)调用该进程设置的信号处理函数(程序中如果先来SIGUSR1信号,然后过来SIGINT信号,则信号处理函数会调用两次,打印不同的内容。第一次打印SIGINT,第二次打印SIGUSR1,因为SIGUSR1是前面阻塞的)

(4)待信号处理函数返回,sigsuspend返回了。(sigsuspend将捕捉信号和信号处理函数集成到一起了)

总结:

在nginx源码中,ngx_master_process_cycle函数中,首先调用了sigprocmask()函数阻塞了部分信号,在for循环中调用了sigsuspend函数 ,但是sigsuspend函数中的set为空,也就是说,在for循环之前,如果有set集合中的信号到来就阻塞,在for循环之内,任何信号到来都进程处理。函数返回之后同时也恢复了原来的信号掩码!

sigsuspend sigprocmask函数的使用方法

时间: 2024-10-12 13:05:38

sigsuspend sigprocmask函数的使用方法的相关文章

sigsuspend sigprocmask函数的用法

一个进程的信号屏蔽字规定了当前堵塞而不能递送给该进程的信号集.调用函数sigprocmask能够检測或更改其信号屏蔽字,或者在一个步骤中同一时候运行这两个操作. #include <signal.h> int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset ); 返回值:若成功则返回0,若出错则返回-1 首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回. 其次,若set是

用户选择,调用相应函数的编写方法

用户选择,调用相应函数的编写方法: 1.先输出Menu菜单,让用户选择. 2.创建一个Menu字典k=序号,v=操作函数 3.调用用户选择的相应序号的函数:menu[option](参数) def account_info(acc_data): print(user_data) def repay(acc_data): pass def withdraw(acc_data): pass def transfer(acc_data): pass def pay_check(acc_data): p

translate()函数的使用方法

以下实例展示了 translate()函数的使用方法: #!/usr/bin/pythonfrom string import maketrans # 引用 maketrans 函数. intab = "aeiou" outtab = "12345" trantab = maketrans(intab, outtab) str = "this is string example....wow!!!";print str.translate(tra

strdup函数的使用方法

函数名: strdup 功  能: 将串复制到新建的位置处 用  法: char *strdup(char *str): 这个函数在linux的man手冊里解释为: The strdup() function returns a pointer toa new string which is a duplicate of the string s. Memory for thenew string is obtained with malloc(3), and can be freed with

【图文】Excel中vlookup函数的使用方法

今天统计数据,用到了Excel中vlookup函数,第一次使用当然少不了百度,经过反复研究后,算是解决了问题,现整理成文档. 一.实现效果 Sheet1 Sheet2   注:上图中sheet1商品条码列(即D列)引用sheet2中商品条码(即B列)中的数据 二.vlookup函数调用说明 以sheet1中调用函数为例,如下: =VLOOKUP(A2,Sheet2!$A$2:$B$100,2,TRUE) 函数中共有四个调用参数 1)  第一个参数:A2 :可任意指定,也可以是B2.C2等.这一列

inline函数的使用方法

 inline关键字用来定义一个类的内联函数,引入它的主要原因是用它替代C中表达式形式的宏定义. 表达式形式的宏定义如下: #define ExpressionName(Var1,Var2) ((Var1)+(Var2))*((Var1)-(Var2)) 为什么要取代这种形式呢,且听我道来: 1. 首先谈一下在C中使用这种形式宏定义的原因,C语言是一个效率很高的语言,这种宏定义在形式及使用上像一个函数,但它使用预处理器实现,没有了参数压栈,代码生成等一系列的操作,因此,效率很高,这是它在C中

JAVA 主函数(主方法)

主函数(主方法) 1.public     (访问修饰符,公共的)代表该类或者该方法访问权限是最大的 2.static    代表主函数随着类的加载而加载 3.void    代表主函数没有具体的返回值 4.main    main不是java中的关键字,它是一个特殊的单词,它能够被JVM(java虚拟机)所识别 5.String[] args    函数的参数类型是一个字符串数组,该数组的元素是字符串,这个数组传入值的方法是在运行的时候传入,例如:javac Index.java 编译java

多返回值函数的编写方法

方法一:利用全局变量 注意,该方法虽然可以实现有多个返回值的函数,但是由于全局变量不能保证值的正确性(因为其作用域是全局,所以程序范围内都可以修改它的值,如果出现错误将非常难以发现),并且全局变量增加了程序间模块的耦合,所以该方法要慎用. 方法二:使用数组指针 注意,该方法适用于多个返回值的数据类型一致的情况. 方法三:使用结构体指针 注意,当函数要求返回的多个值是相互关联的,或者返回的多个值数据类型不一致时可以采用该方法. 详细内容请参考:http://blog.csdn.net/suprem

内容页直接输出图集函数及使用方法

当你想在内容页一张一张地显示图片的时候,你应该打开数据表看一下图片的存放规则哦,你也许看到了,每张图片以换行的方式保存,每行又以大图,小图,图片说明的方式存放这时我们要显示出每张图片,就是要先按行截取,然后再找到每行的分隔符,当然这里是::::::通过分析我们发现帝国有一个接口文件e/class/userfun.php因此我们在这个文件里写下函数: function showpiclist($str){ $imgr=explode("\r\n",$str); $piclist=&quo