linux进程通信----信号的处理
2013-07-04 18:15
330 查看
在了解了信号的产生和捕获之后,接下来就是对信号的具体操作了,特定的信号是与一定的进程相联系的,一个进程可以选择忽略一些信号和处理一些信号,进程可以选择如何处理信号,所以信号是与特定的进程相联系的,因此首先就要建立进程与信号之间的对应关系,这就是信号的处理
ps:信号的注册和信号处理之间的区别:前者信号是主动方,后者是进程是主动方,信号的注册是进程选择处理特定信号之后特定信号的主动行为。
信号处理有两种方法一种是简单的signal()函数,一种是使用信号集函数组
1.信号处理函数
使用signal()时只需指出要处理的信号和处理函数即可,他主要用于前32中非实时的信号,不支持信号传递信息,但使用简单方便,所以得到程序员的欢迎,linux提供一个更健壮,更新的信号处理的函数sigaction(),推荐使用这个函数。
signal()函数语法如下:
这个函数原型有点复杂,可以使用下面的typedef进行替换说明:
sigaction()函数语法如下:
sigaction()函数第二个和第三个参数都有一个signaction结构,其原型如下:
sa_mask-----信号集,可以指定在信号处理过程中哪些信号应当被屏蔽,在调用处理函数之前,信号集需要加入信号的信号屏蔽字中
sa_flags----包含了许多标志位,是对信号处理的各个选项,常用选项如下:
使用signal()的实例:
使用sigaction()函数的如下:
可见两种方法都能实现信号的处理
下面说一下信号集函数组:
信号集函数组处理信号时涉及一系列的函数,这些函数按照调用的先后顺序,可以分为几大功能块:创建信号集合,注册信号处理函数,检测信号
(1)创建信号集合
创建信号集合主要用于处理用户感兴趣的一些信号,函数包括一下几个:
sigemptyset():将信号集合初始化为空
sigfillset():将信号初始化为包含已定义的信号的集合
sigaddset():将指定信号加入到信号集合中去
sigdelset():将指定信号从信号集中删除
sigismember():查询制定信号是否在信号集合中
(2)注册信号处理函数----注册信号处理函数主要用于决定进程如何处理函数,注意的是信号集里的函数并不一定是可以处理的信号,只有信号处于非阻塞状态时才会真正起作用,所以需要使用sigprocmask()检测并更改信号屏蔽字(信号屏蔽字是用来指定当前被阻塞的一组信号,他们不会被进程接收),然后使用sigaction()指定接收到特定信号的处理函数,最后是检测阻塞的信号使用sigpending(),进程可以通过这个函数去检测那些被阻塞的函数,然后决定他们的行为
下面是创建信号集合的函数语法:
如此就指定了信号集合set
sigprocmask的函数语法:
ps:如果set是一个非空指针,那么参数how表示函数的操作方式;如果how为空,则表示忽略此操作
sigpending()函数的语法要点:
所以处理信号的流程如下:
下面是处理信号的实例:
如果们在解锁之前发送SIGINT,SIGQUIT信号,信号不会丢失,等到非阻塞状态时,这些信号还是会被发送给程序的
ps:信号的注册和信号处理之间的区别:前者信号是主动方,后者是进程是主动方,信号的注册是进程选择处理特定信号之后特定信号的主动行为。
信号处理有两种方法一种是简单的signal()函数,一种是使用信号集函数组
1.信号处理函数
使用signal()时只需指出要处理的信号和处理函数即可,他主要用于前32中非实时的信号,不支持信号传递信息,但使用简单方便,所以得到程序员的欢迎,linux提供一个更健壮,更新的信号处理的函数sigaction(),推荐使用这个函数。
signal()函数语法如下:
这个函数原型有点复杂,可以使用下面的typedef进行替换说明:
typedef void sign(int) ; sign *signal(int, header*) ;函数原型指向一个无返回值带一个int类型参数的函数指针,而该函数原型带有两个参数,第二个参数是自定义的处理函数的指针
sigaction()函数语法如下:
sigaction()函数第二个和第三个参数都有一个signaction结构,其原型如下:
struct sigaction { void (*sa_handler)(int signo) ; sigset_t sa_mask ; int sa_flags ; void (*sa_restore)(void) ; };sa_handler---是一个函数指针,指定信号处理函数,除了用户自定义的处理函数外,还可以是SIG_DFL(采用缺省的处理方式)或SIG_IGN(忽略信号),处理函数只有一个参数,就是信号值
sa_mask-----信号集,可以指定在信号处理过程中哪些信号应当被屏蔽,在调用处理函数之前,信号集需要加入信号的信号屏蔽字中
sa_flags----包含了许多标志位,是对信号处理的各个选项,常用选项如下:
使用signal()的实例:
#include <signal.h> #include <stdio.h> #include <stdlib.h> void my_func(int sign_no) { if (sign_no == SIGINT) { printf("i have get SIGNINT\n") ; } else if (sign_no == SIGQUIT) { printf("i have get SIGQUIT\n") ; } } int main() { printf("waiting for signal or sigquit...\n") ; //当信号来临是由my_func函数处理 signal(SIGINT, my_func) ; signal(SIGQUIT, my_func) ; pause() ; exit(0) ; }
使用sigaction()函数的如下:
#include <signal.h> #include <stdio.h> #include <stdlib.h> void my_func(int sign_no) { if (sign_no == SIGINT) { printf("i have get SIGNINT\n") ; } else if (sign_no == SIGQUIT) { printf("i have get SIGQUIT\n") ; } } int main() { struct sigaction action ; printf("waitfor signal SIGINT OR SIGQUIT...\n ") ; //初始化action结构体 action.sa_handler = my_func ;//指定处理函数 sigemptyset(&action.sa_mask) ;//将信号集加入信号屏蔽字中 action.sa_flags = 0 ; //定义相关处理函数 sigaction(SIGINT, &action, 0) ; sigaction(SIGQUIT, &action , 0) ; pause() ; exit(0) ; }运行结果如下:
可见两种方法都能实现信号的处理
下面说一下信号集函数组:
信号集函数组处理信号时涉及一系列的函数,这些函数按照调用的先后顺序,可以分为几大功能块:创建信号集合,注册信号处理函数,检测信号
(1)创建信号集合
创建信号集合主要用于处理用户感兴趣的一些信号,函数包括一下几个:
sigemptyset():将信号集合初始化为空
sigfillset():将信号初始化为包含已定义的信号的集合
sigaddset():将指定信号加入到信号集合中去
sigdelset():将指定信号从信号集中删除
sigismember():查询制定信号是否在信号集合中
(2)注册信号处理函数----注册信号处理函数主要用于决定进程如何处理函数,注意的是信号集里的函数并不一定是可以处理的信号,只有信号处于非阻塞状态时才会真正起作用,所以需要使用sigprocmask()检测并更改信号屏蔽字(信号屏蔽字是用来指定当前被阻塞的一组信号,他们不会被进程接收),然后使用sigaction()指定接收到特定信号的处理函数,最后是检测阻塞的信号使用sigpending(),进程可以通过这个函数去检测那些被阻塞的函数,然后决定他们的行为
下面是创建信号集合的函数语法:
如此就指定了信号集合set
sigprocmask的函数语法:
ps:如果set是一个非空指针,那么参数how表示函数的操作方式;如果how为空,则表示忽略此操作
sigpending()函数的语法要点:
所以处理信号的流程如下:
下面是处理信号的实例:
#include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <signal.h> void my_func(int signum) { printf("if you want to quit, please try SIGQUIT!\n") ; } int main() { sigset_t set, pendset ; struct sigaction action1, action2 ; if (sigemptyset(&set) < 0)//信号集初始化为空 { perror("sigemptyset") ; exit(1) ; } if (sigaddset(&set, SIGINT) < 0)//将SIGINT加入到信号集set { perror("sigaddset") ; exit(1) ; } if (sigaddset(&set, SIGQUIT) < 0)//将SIGQUIT加入到信号集set中 { perror("sigaddset") ; exit(1) ; } if (sigismember(&set, SIGINT)) { sigemptyset(&action1.sa_mask) ;//没有屏蔽的信号 action1.sa_handler = my_func ; action1.sa_flags = 0 ; sigaction(SIGINT, &action1, NULL) ;//定义SIGINT的处理函数my_func } if (sigismember(&set, SIGQUIT)) { sigemptyset(&action2.sa_mask) ;//没有屏蔽的信号 action2.sa_handler = SIG_DFL ; action2.sa_flags = 0 ; sigaction(SIGQUIT, &action2, NULL) ;//定义SIGQUIT的处理为默认 } if (sigprocmask(SIG_BLOCK, &set, NULL) < 0)//阻塞信号集set中的信号 { perror("sigprocmask") ; exit(1) ; } else { printf("signal set was blocked, press any key!\n") ; getchar() ; } if (sigprocmask(SIG_UNBLOCK, &set, NULL) < 0)//将set中的信号变为非阻塞态 { perror("sigprocmask") ; exit(1) ; } else { printf("signal set is in unblock state\n") ; } while(1) ;//循环处理 exit(0) ; }程序运行如下:
如果们在解锁之前发送SIGINT,SIGQUIT信号,信号不会丢失,等到非阻塞状态时,这些信号还是会被发送给程序的
相关文章推荐
- Linux下信号通信实现A进程死循环输出A后被C进程处理输出C
- Linux向进程发送信号及执行信号处理函数的时机
- linux 进程信号通信
- linux 进程通信---信号signal
- 进程通信之linux信号机制
- linux下的僵尸进程处理SIGCHLD信号
- Linux进程通信 发送信号
- Linux C语言编程-Linux网络通信--Linux上使用套接字(socket)来处理信息---编写一个单进程非阻塞多客户的套接字客户端
- linux进程通信之信号
- linux下的僵尸进程处理SIGCHLD信号
- Linux进程间信号通信
- 说说Linux中的信号处理和僵尸进程的避免
- Linux进程通信-信号学习
- linux 下进程间通过信号进行通信的具体实现过程
- linux基础编程:进程通信之信号
- linux多进程——进程组与会话、守护进程、信号通信 .
- Linux 进程通信之 ——信号和信号量总结
- linux进程通信-信号机制
- linux 进程通信之 信号
- linux信号处理、killall、SIGALRM、sigaction函数和结构体、向进程发送信号