linux高编信号-------信号集
信号集的函数:
类型:sigset_t 类型
#include <signal.h> /**************************** *功能:把一个信号集的内容清空 *参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数 *返回值:成功返回0,失败返回-1 * ************************/ int sigemptyset(sigset_t *set); /**************************** *功能:把一个信号集的内容填满,包含所有的信号 *参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数 *返回值:成功返回0,失败返回-1 * ************************/ int sigfillset(sigset_t *set); /**************************** *功能:把一个信号添加到信号集中 *参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数 *返回值:成功返回0,失败返回-1 * ************************/ int sigaddset(sigset_t *set, int signum); /**************************** *功能:把一个信号从信号集中删除 *参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数 *返回值:成功返回0,失败返回-1 * ************************/ int sigdelset(sigset_t *set, int signum); /**************************** *功能:判断是否是信号是否在指定集合中 *参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数 *返回值:成功返回0,失败返回-1 * ************************/ int sigismember(const sigset_t *set, int signum);
#include <signal.h> /***************信号屏蔽字*********** *功能:检查和更改阻塞信号 *参数:how:SIG_BLOCK:阻塞(eg:阻塞住set中的信号成员) * set:信号集所有对象 *返回值:成功返回0,失败返回-1 * **********************************/ int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
/***************************************** *功能:等待一个信号(pause) *步骤1:设置新的mask阻塞当前进程 *步骤2:收到信号,调用该进程设置的信号处理函数 *步骤3:待信号处理函数返回后,恢复之前的mask * **************************************/ int sigsuspend(const sigset_t *mask);
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> void func(int s) { write(1,"!",1); } int main(void) { int i , j ; sigset_t set ,oset ,saveset ; //1.设置信号 signal(SIGINT,func); //2.信号集清空 sigemptyset(&set); //3.将信号SIGINT添加到信号集 sigaddset(&set , SIGINT); //4.将信号集中信号从当前的信号掩码中删除,并保存UNBLOCK之前的信号状态 // 保存模块使用前的状态不被改变 sigprocmask(SIG_UNBLOCK , &set , &saveset); //5.将信号集中的信号加到信号掩码中使用,并保存BLOCK之前的信号状态 sigprocmask(SIG_BLOCK , &set , &oset); //6.打印*****换行 for(i = 0 ; i < 1000 ; i++) { for(j = 0 ; j < 5 ; j++) { write(1 , "*",1); sleep(1); } write(1,"\n",1); //7.等待一个信号,信号到来驱动程序进行 sigsuspend(&oset);//原子操作 #if 0 sigset_t tmpset ; sigprocmask(SIG_SETMASK , &oset ,&tmpset);//解除阻塞 pause();//等待信号 sigprocmask(SIG_SETMASK , &tmpset ,&NULL);//恢复阻塞 #endif } //8.恢复之前的状态(要有模块概念,不应该更改信号前的状态)与4对应 sigprocmask(SIG_SETMASK , &saveset , NULL); exit(0); }
/************************ *功能:替代signal函数:检查或者修改指定信号相关处理函数 *参数:signum:信号num * act:定义新的行为 * oldact:保存旧的行为 * **********************/ int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact); struct sigaction { void (*sa_handler)(int);//替换signal void (*sa_sigaction)(int, siginfo_t *, void *);//具有三个参数的信号处理函数 sigset_t sa_mask;//需要block住的信号 int sa_flags;//特殊要求 void (*sa_restorer)(void); };
eg:
/*********************** *功能:创建守护进程 * 添加系统日志 * ********************/ #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <syslog.h> #include <errno.h> #include <signal.h> //守护进程创建后不断向FNAME中写入数字 #define FNAME "/tmp/out" static FILE *fp ; static int daemonize(void ) { pid_t pid ; int fd ; int i ; //1.创建进程 pid = fork(); if(pid < 0) return -1; //2.子进程 if(pid == 0) { //脱离控制终端 读写形式打开一个设备 fd = open("/dev/null",O_RDWR); if(fd < 0) return -1 ; //重定向:将fd重定向到0 ,1 ,2 dup2(fd , 0 ); dup2(fd , 1 ); dup2(fd , 2 ); if(fd > 2) close(fd); //守护进程产生 setsid(); //当前的工作路径为根目录,如果是挂载的文件卸载可能回busy chdir("/"); //在程序中不会产生文件的情况下 umask(0); return 0 ; } else//2.父进程 exit(0); } /*当信号处理函数实现过程中 * 多个信号共用同一个处理函数的时候 * 在处理一个信号的过程中 * 需要把其他的信号block住*/ static void damon_exit(int s ) { fclose(fp); closelog(); exit(0); } int main() { int i ; struct sigaction sa ; /*sigaction使用*/ sa.sa_handler = damon_exit ; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask , SIGQUIT); sigaddset(&sa.sa_mask , SIGTERM); sigaddset(&sa.sa_mask , SIGINT); sa.sa_flags = 0 ; sigaction(SIGINT,&sa,NULL); sigaction(SIGQUIT,&sa,NULL); sigaction(SIGTERM,&sa,NULL); /*多个信号用一个信号处理函数:如果有重入的危险*/ //signal(SIGINT,damon_exit); //signal(SIGQUIT,damon_exit); //signal(SIGTERM,damon_exit); //0.建立系统日志 openlog("mydeamon",LOG_PID,LOG_DAEMON); //1.创建守护进程 if(daemonize()) { syslog(LOG_ERR ,"deamonize() failed !"); exit(1); } else { syslog(LOG_INFO,"deamonize() success !"); } //===========守护进程工作============== //2.以写的方式打开文件 fp = fopen(FNAME , "w"); if(fp == NULL) { syslog(LOG_ERR,"fopen()%s",strerror(errno)); exit(1); } syslog(LOG_INFO ,"%s was opened",FNAME); //3.不断写入i的值eg:1 2 3 4 ...... for(i = 0 ;; i++) { fprintf(fp,"%d\n",i); //文件全缓冲模式,要加刷新 syslog(LOG_DEBUG , "%d is printed ",i); fflush(fp); sleep(1); } exit(0); }^_