信号编程之信号发送及信号处理函数遇到不可重入函数
来源:互联网 发布:qq老密数据库下载 编辑:程序博客网 时间:2024/06/09 12:49
kill函数
- 函数原型:
Int kill(pid_t pid, int siq)
- 功能:既可以向自身发送信号,也可以向其他进程发送信号;
- 参数:
- pid>0 将信号sig发给pid进程
- pid=0 将信号sig发给同组进程
- pid=-1 将信号sig发送给所有进程,调用者进程有权限发送的每一个进程(除了1号进程之外,还有它自身)
- pid<-1 将信号sig发送给进程组是pid(绝对值)的每一个进程
注意,如果在fork之前安装信号,则子进程可以继承信号。
补充:getpgrp()函数获取进程组pid
sleep函数
函数原型:unsigned int sleep(unsigned int seconds);
功能:让进程睡眠。原理和wait类似,都有可能被其他信号打断!
注意:
1)能被信号打断,然后处理信号函数以后,就不再睡眠了。直接向下执行代码
2)sleep函数的返回值,是剩余的秒数
- 示例代码:
#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <signal.h>#include <unistd.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/types.h>#include <fcntl.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <signal.h>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 = getpgrp(); pid = getppid(); //kill(pid, SIGUSR1); //向老爹发信号 kill(0, SIGUSR1); //向进程组发信号 //killpg(pid, SIGUSR1); exit(0); } */ if (pid == 0) { pid = getpgrp(); killpg(pid, SIGUSR1); exit(0); } int n = 3; do { printf("父进程开始睡眠\n"); n = sleep(n); printf("父进程开始唤醒\n"); } while (n > 0); //sleep(n); printf("sleep 函数执行完毕以后返回...\n"); return 0;}
raise函数
函数原型: int raise(int sig);
功能:给自己发送信号。raise(sig)等价于kill(getpid(), sig);
kill可以发送信号给其他进程
killpg函数
函数原型:int killpg(int pgrp, int sig);
功能:给进程组发送信号。killpg(pgrp, sig)等价于kill(-pgrp, sig);
sigqueue函数
函数原型:int sigqueue(pid_t pid, int sig, const union sigval value);
函数功能: 给进程发送信号,支持排队,可以附带信息
pause函数
- 将进程置为可中断睡眠状态。然后它调用内核函数schedule(),使linux进程调度器找到另一个进程来运行。
- pause使调用者进程挂起,直到一个信号被捕获就返回,不再阻塞调用者进程。
alarm函数
功能:设置一个闹钟延迟发送信号。告诉linux内核n秒以后,发送SIGALRM信号;
函数原型:unsigned int alarm(unsigned int seconds);
注意:该闹钟只是一次有效,如果要重复有效,则需要在信号处理函数里面再次调用alarm函数设置闹钟。
void myhandle(int num){ printf("recv signal id num : %d \n", num); alarm(1);}int main(void){ printf("main ....begin\n"); //注册信号处理函数 if (signal(SIGALRM, myhandle) == SIG_ERR) { perror("func signal err\n"); return 0; } alarm(1); while(1) { pause(); printf("pause return\n"); } return 0;}
信号处理函数遇上可重入和不可重入函数
所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。因为进程在收到信号后,就将跳转到信号处理函数去接着执行。--也就是说可重入函数可以被多个进程或者函数同时调用,但不必关心内部数据和全局数据是否会被修改。
如果信号处理函数中使用了不可重入函数,那么信号处理函数可能会修改原来进程中不应该被修改的数据,这样进程从信号处理函数中返回接着执行时,可能会出现不可预料的后果。不可重入函数在信号处理函数中被视为不安全函数。
满足下列条件的函数多数是不可再入的:
(1)使用静态的数据结构,如getlogin(),gmtime(),getgrgid(),getgrnam(),getpwuid()
以及getpwnam()
等等;
(2)函数实现时,调用了malloc()
或者free()
函数
(3)实现时使用了标准I/O函数的
结论:在信号处理函数中,尽量不使用含有全局变量和静态变量的函数。特别是这个变量在程序中随时可能读写。
man 7 signal 查找可重入函数和不可重入函数。
#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <signal.h>typedef struct _Teacher{ int age; int num; }Teacher;Teacher g_t;char *p = NULL:void printfGlobTeacher(){ printf("g_t.age:%d \n", g_t.age);//含有全局变量--不可重入--gt一直在改变 printf("g_t.num:%d \n", g_t.num); //p = malloc(100);//容易引起不可重入}void myhandle(int num){ printf("recv signal id num : %d \n", num); printfGlobTeacher(); alarm(1);}int main(void){ Teacher t1, t2; t1.age = 30; t1.num = 30; t2.age = 40; t2.num = 40; printf("main ....begin\n"); //注册信号处理函数 if (signal(SIGALRM, myhandle) == SIG_ERR) { perror("func signal err\n"); return 0; } //间接递归 //myhandle----->alarm=====>myhandle alarm(1); while(1) { g_t = t1; g_t = t2; } return 0;}
- 信号编程之信号发送及信号处理函数遇到不可重入函数
- 十六、Linux系统编程-信号(三)其他信号发送函数、可重入及不可重入函数
- 信号处理函数遇上不可重入函数
- 信号可靠与不可重入函数
- 信号捕捉预处理之不可重入函数
- 信号处理程序中调用不可重入函数getpwnam 起结果是不可预见的。
- unix 环境高级编程 信号二 可重入函数与不可重入函数
- 信号处理函数的返回及信号的发送
- linux系统编程之信号(六):信号发送函数sigqueue和信号安装函数sigaction
- linux系统编程之信号(六):信号发送函数sigqueue和信号安装函数sigaction
- linux系统编程之信号(六):信号发送函数sigqueue和信号安装函数sigaction
- shell捕捉信号,重定向信号处理函数
- 信号编程之signal函数
- linux系统编程之信号(二):一些信号发送函数和不同精度的睡眠
- linux系统编程之信号(二):一些信号发送函数和不同精度的睡眠
- linux系统编程之信号(二):一些信号发送函数和不同精度的睡眠
- linux系统编程之信号(二):一些信号发送函数和不同精度的睡眠
- 信号及信号处理
- Swift 3.0 第三方库不适配报(SWIFT_VERSION)问题
- 通过input propertychange实现即时搜索
- java路径读取方法
- iReport中产生二维条码(zxing)
- 深度学习word2vec笔记之算法篇
- 信号编程之信号发送及信号处理函数遇到不可重入函数
- 不要消费信任
- Linux下的fdisk用法
- 【45.65%】【codeforces 560B】Gerald is into Art
- 安装Ubuntu系统,你如何分区滴~?
- freeswitch之多分机顺振
- Java 求余操作符
- SVN linux下的安装与使用
- ubuntu14.04 node.js快速安装