信号(二)

1.向另一个进程发送信号 ①kill函数 int kill(pid_t pid, int siq)
pid>0   信号sig发给pid进程  
pid=0   将信号sig发给同组进程  
pid=-1   将信号sig发送给所有进程,调用者进程有权限发送的每一个进程(除了1号进程之外,还有它自身)  
pid<-1   将信号sig发送给进程组是pid(绝对值)的每一个进程  
例:子进程向父进程(同组进程)发送信号 void myhandle(int num) { if (num == SIGINT) { printf("recv signal SIGINT \n"); } else if (num == SIGUSR1) { printf("recv signal SIGUSR1 \n"); } else { printf("recv signal id num : %d \n", num); } } int main(void) { pid_t pid; printf("main ....begin\n"); if (signal(SIGINT, myhandle) == SIG_ERR) { perror("func signal err\n"); return 0; } if (signal(SIGUSR1, myhandle) == SIG_ERR) { perror("func signal err\n"); return 0; } pid = fork(); if (pid == -1) { printf("fork err....\n"); return 0; } //子进程向父进程发送信号 //子进程向同组进程发送信号 if (pid == 0) { pid = getppid(); kill(pid, SIGUSR1); //向父进程发信号 //向进程组发信号 kill(0, SIGUSR1); //法一 //pid = getpgrp(); //法二 //killpg(pid, SIGUSR1); exit(0); } printf("sleep 函数执行完毕以后返回...\n"); return 0; } ②raise函数 给自己发送信号。raise(sig)等价于kill(getpid(), sig); ③sigqueue函数 int sigqueue(pid_t pid, int sig, const union sigval value) 价格
功能   针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。  
返回值   成功:0,失败:-1  
参数
pid   指定接收信号的进程id  
sig   发送的信号  
value   信号传递的参数  
其中第三个参数为union sigval,下面是union sigval的内容: typedef union sigval { int sival_int; void *sival_ptr; }sigval_t;

注:在下面介绍的sigaction()函数的第二个参数结构体参数中,第二个处理器函数siginfo_t参数下有一个sigval_t值。。。

例:两个进程间通过 sigqueue 发送数据 void myHandle_forsigaction(int signum, siginfo_t *s_t, void *p) { int myint = 0; printf("recv signum : %d \n", signum); myint = s_t->si_value.sival_int; printf("%d %d \n", myint, s_t->si_int ); } int main(int argc, char *argv[]) { pid_t pid; int ret = 0; struct sigaction act; act.sa_sigaction = myHandle_forsigaction; sigemptyset(&act.sa_mask); //准备接受额外数据 act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, NULL) < 0) ERR_EXIT("sigaction error"); pid = fork(); if (pid == -1) { printf("fork err...\n"); return 0; } if (pid == 0) { int i = 0; /* Teacher *t = (Teacher *)malloc(sizeof(Teacher)); memset(t, 0, sizeof(Teacher)); strcpy(t->name, "name"); t->age = 33; */ /* union sigval { int sival_int; void *sival_ptr; }; */ union sigval mysigval; //mysigval.sival_ptr = (void *)&t; mysigval.sival_int = 222; //kill(getppid(), SIGINT); //带额外数据 for (i=0; i<10; i++) { ret = sigqueue(getppid(), SIGINT, mysigval); if (ret != 0) { printf("sigqueue .....\n"); exit(0); } else { printf("sigqueue...successs\n"); sleep(2); } } } else if (pid > 0) { for (;;) pause(); } return 0; } 2.改变信号处置 从上一节可知,信号抵达后,有着不同的处理方式,如 `SIG_DFL` :执行默认的方式; `SIG_IGN` :忽略;或者执行信号处理器程序(即程序员自己编写的程序)。 首先介绍如何实现信号处理器程序。 ①signal函数 __sighandler_t signal(int signum, __sighandler_t handler);
功能   忽略信号、设置信号默认处理或注册一个信号处理函数  
返回值   返回修改前的handler函数指针  
参数
signum   信号类型  
handler   接收到指定信号时将要调用的函数  
例1:信号的安装(注册SIGINT) void handler(int num) { printf("recv num:%d \n", num); } void main() { //注册一个信号 //SIGINT 是ctrl+c 会产生2号信号。。。 中断应用程序 signal(SIGINT, handler); while(1) { pause(); } printf("main...Begin\n"); } 例2:信号的恢复 int main(void) { __sighandler_t oldHandle; //保留原处理信号行为 printf("main ....begin\n"); oldHandle = signal(SIGINT, myhandle); if (oldHandle == SIG_ERR) { perror("func signal err\n"); return 0; } printf("if u enter a, reset signal \n"); while(getchar() != 'a') { ; } //键入a以后,信号的恢复 //法一:恢复默认函数 /* if (signal(SIGINT, oldHandle) == SIG_ERR) { perror("func signal err\n"); return 0; } */ //法二: if (signal(SIGINT, SIG_DFL) == SIG_ERR) { perror("func signal err\n"); return 0; } while(1) ; return 0; } ②sigaction函数 int sigaction(int signum,const struct sigaction act,const struct sigaction old)
功能   注册一个信号处理函数  
返回值   成功:0,失败:-1  
参数
signum   信号类型  
act   指向结构sigaction的一个实例的指针  
old   保存原来对相应信号的处理  
第二个参数act包含了对指定信号的处理、信号所传递的信息、信号处理函数执行过程中应屏蔽掉哪些信号等等。下面是struct sigaction的内容: struct sigaction { void (*sa_handler)(int); //信号处理程序一: 不接受额外数据,同signal()的第二个参数 void (*sa_sigaction)(int, siginfo_t *, void *); //信号处理程序二:能接受额外数据,和sigqueue配合使用 sigset_t sa_mask; //定义一组信号,不允许中断此处处理程序的执行 int sa_flags; //影响信号的行为 SA_SIGINFO表示能接受数据 void (*sa_restorer)(void); //废弃 }; 由于struct sigaction结构中信号处理程序一与之前在signal中介绍的处理函数相似,所以接下来介绍信号处理程序二的使用。 第二个参数siginfo_t内容如下: siginfo_t { int si_signo; /* Signal number */ int si_errno; /* An errno value */ int si_code; /* Signal code */ pid_t si_pid; /* Sending process ID */ uid_t si_uid; /* Real user ID of sending process */ int si_status; /* Exit value or signal */ clock_t si_utime; /* User time consumed */ clock_t si_stime; /* System time consumed */ sigval_t si_value; /* Signal value */ int si_int; /* POSIX.1b signal */ void * si_ptr; /* POSIX.1b signal */ void * si_addr; /* Memory location which caused fault */ int si_band; /* Band event */ int si_fd; /* File descriptor */ }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydwjg.html