linux系统中的信号处理
来源:互联网 发布:mac怎么文件夹压缩 编辑:程序博客网 时间:2024/05/01 06:07
1.1信号的概念
信号:信号是异步传送给进程的时间通知,进程无法准确地预测合适会出现信号。
同步信号:程序中的某个具体的操作相关并且在那个操作进行的同时产生。
异步信号:进程之外的事件产生的信号。
当信号发生时进程采取的动作:
1)忽略信号。
2)捕获信号。
3)执行系统默认动作。
1.2 kill( )函数
#include <signal.h>int kill(pid_t pid, int sig);pid > 0:把信号发送给ID为pid的进程。
pid == 0:把信号发送给进程所在进程组的所有进程。
pid < -1:把发送给ID为pid的绝对值的进程组(发送者有权发送)。
pid == -1:广播信号,发送给发送者有权发送的所有进程。
sig:信号。
执行成功返回0,失败返回-1并且置error指出错误原因。
为了防止随意的杀死属于其他用户的进程,一般发送信号的实际用户ID或有效ID必须与接受信号的实际用户ID或有效ID相同。root用户有权向任意用户发送信号。
使用kill( )函数发送信号的例子:
#include <signal.h>#include <stdio.h>#include <stdlib.h>int flag = 0; /*标志变量*/void sig_usr(int sig) /*信号句柄*/{flag = 1;}void child() /*子进程调用,发送给父进程SIGUSR1信号*/{printf("My Pid is %d \n",(int)getpid());kill(getppid(),SIGUSR1);printf("life over!\n");exit(0);}int main(){pid_t ch;signal(SIGUSR1,sig_usr); /*设置信号动作*/if((ch = fork()) == -1) /*如果创建子进程失败,退出*/{fprintf(stderr,"faild!\n");exit(-1);}if(ch == 0) /*如果是子进程*/child();while(!flag); /*循环等待SIGUSR1信号的出现*/fprintf(stdout,"voer!\n");return 0;}1.3设置信号动作
#include <signal.h>typedef void (*sighandler_t) (int);sighandler_t signal(int signum,sighandler_t handler);signum:指明是那种信号。
handler:信号发生时应该采取的动作。
返回值:前一次有效动作的指针。
signal的缺陷:
void sig_usr(int sig){ ....... signal(SIGUSR1 sig_usr); /*设置SIGUSR1信号句柄*/}int main(){ signanl(SIGUSR1,sig_usr); ...}当在执行SIGUSR1信号句柄时,SIGUSR1信号在执行设置SIGUSR1信号句柄前出现,将导致进程的终止。因为在执行信号句柄时系统将重置该信号的动作为默认动作。signal是不可靠的,应该使用可靠的sigaction设置信号的动作。
使用signal( )设置信号的动作:
#include <signal.h>#include <stdlib.h>#include <stdio.h>#include <unistd.h>static void sig_usr(int sig) /*信号句柄*/{fprintf(stdout,"voer!\n");return;}int main(){if(signal(SIGUSR1,sig_usr) == SIG_ERR) /*设置信号动作*/{fprintf(stderr,"failg!\n");exit(1);}while(1) /*挂起直到有SIGUSR1信号出现*/{ pause();} return 0;}
sigaction( )函数
#include <signal.h>int sigaction(int signum,const strcut sigaction *act,strcut sigaction *oact);signum:制定的信号。
act:设置信号的动作。
oact:保存前一信号的动作。
act为NULL,oact不为NULL查询当前的信号动作。
act不为NULL,oact为NULL设置信号动作。
act,oact不为NULL,设置信号动作,并保存前一信号动作。
调用成功返回0,不成功返回-1,且不安装新动作;
结构体sigaction定义:
struct sigaction{ void (*sa_handler) ( ); void (*sa_sigaction) (int,siginfo_t*,siginfo*); sigset_t sa_mask; int sa_flags;};
第一个成员变量:指定与信号相连的动作,指定一个信号句柄。
第二个成员变量:指定与信号相连的动作,指定一个信号句柄。
第三个成员变量:sa_mask要屏蔽的信号集合。
第四个成员变量:sa_flags 标志变量。
#include <signal.h>int sigempty(sigset_t *set); /*清空信号集合*/int sigfillset(sigset_t *set); /*填满信号集合*/int sigaddset(sigset_t *set,int signo); /*向信号集合中添加信号*/int sigdelset(sigset_t *set,int signo); /*删除集合中的指定信号*/int sigismember (const sigset_t *set,int signo); /*查看信号机中的成员*/调用失败返回-1,成功返回0;
设置屏蔽信号:
#include <signal.h>int sigprocmask (int how,const sigset_t *set,sigset_t *oset); /*改变调用进程的状态*/
how:如何改变信号的屏蔽。
SIG_BLOCK:阻塞set所指信号集的信号集,即将它们加入到当前的信号屏蔽中。
SIG_UNBLOCK:放开set所指的信号集,即将它们从当前的信号屏蔽中删除。
SIG_SETMASK:用set所指的信号集作为进程新的信号集,抛弃原先的信号屏蔽值。
set为NULL,oset不为NULL只查看,不改变。
set不为NULL,oset为NULL只改变。
set和oset都部位NULL,改变屏蔽信号,保存前一信号到oset。
sigpromask( ) 不能阻塞SIGKILL和SIGSTOP信号。
检查挂起信号:
#include <signal.h>int sigpending (sigset_t *set); /*检查挂起信号*/
检查挂起信号:
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <unistd.h>int main(){sigset_t base,old,work; /*定义信号集*/int sig;sigemptyset(&base); /*清空将要设置的信号集*/sigaddset(&base,SIGQUIT); /*添加SIGQUIT信号*/sigaddset(&base,SIGSTOP); /*添加SIGSTOP信号*/if(sigprocmask(SIG_BLOCK,&base,&old) < 0) /*屏蔽base信号集的信号*/fprintf(stderr,"mask faile!\n");fprintf(stdout,"Plase weite!\n");sleep(10); /*睡眠10秒*/sigpending(&work); /*查看挂起的信号集*/for(sig = 1; sig < NSIG; sig++) /*遍历挂起的信号集*/if(sigismember(&work,sig))psignal(sig,"there is a pending signel!\n");if(sigprocmask(SIG_BLOCK,&old,NULL) < 0) /*恢复旧的屏蔽信号*/exit(1);printf("over!\n");exit(0); /*退出*/}
1.5 等待信号
include <unistd.h>voud pause(void) /*挂起调用进程直到有信号到达*/只有这个信号执行句柄函数并且句柄函数返回时,pause()系统调用才会返回。
paus()隐藏这严重的时间窗口错误,导致程序的神秘挂起。
<span style="font-size:14px;">#include <signal.h>int sigsuspend(cost sigset_t *sigmask); /*挂起sigmask信号集,知道有不属于sigmask信号集的信号到来*/</span>使用sigmask的信号集暂时代替进程的信号屏蔽,挂起调用进程直到有不属于sigmask的信号到来。
#include <signal.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>volatile int falg = 0;static void sig_usr(int signo) /*信号SIGUSR1和信号SIGUSR2的语句柄*/{psignal(signo,"received!\n");}static void sig_intr(int signo) /*信号SIGINT的语句柄,置位标识变量*/{psignal(signo,"received!\n"); falg = 1;}void wait_for_signal(int sig,volatile int *f) /**/{static sigset_t mask,oldMask;sigemptyset(&mask); /*清空信号集*/sigaddset(&mask,sig); /*添加信号集*/if(sigprocmask(SIG_BLOCK,&mask,&oldMask) < 0) /*暂时屏蔽mask信号的集合*/{fprintf(stderr,"SIG_BOLK error!\n");exit(1);} sigdelset(&oldMask,SIGUSR1); /*从前一信号集合中删除SIGUSR1*/ sigdelset(&oldMask,SIGUSR2); /*从前一信号集合中删除SIGUSR2*/while(!*f) /*循环等待SIGINT信号的到来*/{printf("Open!\n");sigsuspend(&oldMask);printf("Close\n");}*f = 0;if(sigprocmask(sig,&oldMask,NULL) < 0) /*恢复前一屏蔽信号集*/fprintf(stderr,"fail\n");}int main(){pid_t pid;static sigset_t mask,oldmask;signal(SIGUSR1,sig_usr); /*为SIGUSR1信号添加语句柄*/signal(SIGUSR2,sig_usr); /*为SIGUSR2信号添加语句柄*/signal(SIGINT,sig_intr); /*为SIGINT信号添加语句柄*/sigemptyset(&mask); /*清空mask信号集*/sigaddset(&mask,SIGUSR1); /*添加SIGUSR1信号集合*/sigaddset(&mask,SIGUSR2); /*添加SIGUSR2信号集合*/if(sigprocmask(SIG_BLOCK,&mask,&oldmask) < 0) /*暂时屏蔽mask信号集合*/{fprintf(stderr,"SIG_BLOCK\n");exit(1);}if((pid = fork()) == 0) /*创造子进程*/{kill(getppid(),SIGUSR1); /*给父进程发送SIGUSR1信号*/kill(getppid(),SIGUSR2); /*给父进程发送SIGUSR2信号*/printf("child OK\n"); while(1); /*循环等待*/}else{wait_for_signal(SIGINT,&falg);printf("Now,I can do my work!\n"); kill(pid,SIGTERM); /*杀死子进程*/}exit(0);}
1.6 原子数据
对它的访问操作不会在半途中断的数据,任何访问它的操作要么没有完成,要么已经完成,不存在中间状态。
- linux系统中的信号处理
- Linux中的信号处理
- Linux系统中的信号
- linux系统中的信号
- Linux系统中的信号
- linux系统中的信号
- linux内核中的信号机制--信号处理
- Linux中的信号处理原理
- linux中的信号处理机制
- Linux中的信号处理函数
- linux系统中的实时信号
- Linux系统编程4.信号处理
- linux 信号&信号处理
- linux 信号&信号处理
- linux 信号&信号处理
- linux信号处理 --和信号相关的几个系统调用
- Linux系统编程--信号及信号处理(一)
- Linux系统编程--信号及信号处理(二)
- javascript内置对象--------FileStystemObject对象
- 第2周项目2-程序的多文件组织
- 不懂技术不要对懂技术的人说这很容易实现
- mysql数据库优化原则
- 苹果加急审核详细步骤
- linux系统中的信号处理
- 项目0-宣告“主权”
- 第二周项目3-体验复杂度-两种排序算法的运行时间
- C++ final 和 override 说明符
- 第二周项目0-宣告“主权”
- ResourceUtils
- 关于hashMap的一
- android sdk自带的fragment标签使用
- 部署命令