Linux—signal(usr mode application) 编程

Linux—signal(usr mode application) 编程#<unistd.h>#<sys/types.h>uid_tgetuid(void);uid_tgeteuid(void);组ID,有效组IDuid_tgetgid(void);uid_tgetegid(void);信号不可靠的signalAPI#<signal.h>void(*signal)(intsig,void(*func)(int)))(int)typedefvoid(*sig_t)(int);或sig_tsignal(intsig,sig_tfunc);参数:sig为要为其注册一种操作的信号,func为信号处理函数指针信号说明:SIGHUP终端线已经挂起SIGINT终端线已经接收到中断字符SIGQUIT终端线已经接收到退出字符SIGUSR1用户自定义信号1SIGUSR2用户自定义信号2SIGTERM正被终止的进程SIGCHLD一个子进程已终止SIGPIPE半关闭管道的写操作已经发生SIGALRMAlarm函数的计时器已经到期信号处理函数取值:SIG_DEL默认的信号操作(DEFault)SIG_IGN忽略信号(IGNore)函数指针信号处理函数例:#include<signal.h>#include<stdio.h>#include<unistd.h>staticintcount=0;voidhandler(intsigno){//signal(SIGINT,handler);count++;printf(“GotSIGINT/n”);}intmain(void){signal(SIGINT,handler);while(count<2){printf(“WaitingforSIGINT…/n”);sleep(3);}puts(“end/n”);return0;}可靠信号API要使用可靠信号必须使用信号集,构造信号集的数据类型sigset_t<signal.h>intsigemptyset(sigset_t*set);清空信号集,使其成为无信号状态sigset_tmy_sigs;sigemptyset(&my_sigs);初始化my_sigs信号集,使其不包含任何信号intsigfillset(sigset_t*set);将所有可用信号填充进信号集sigset_tmy_sigs;sigfillset(&my_sigs);初始化信号集,以包含每个可用的信号intsigaddset(sigset_t*set,intsignum);将一个指定的信号添加进信号集sigset_tmy_sigs;sigemptyset(&my_sigs);sigaddset(&my_sigs,SIGINT);sigaddset(&my_sigs,SIGPIPE);清空信号集再添加两个信号intsigdelset(sigset_t*set,intsignum);从信号集中删除指定的信号sigset_tmy_sigs;sigfillset(&my_sigs);sigdelset(&my_sigs,SIGINT);填充信号集再删除SIGINT信号intsigismember(constsigset_t*set,intsignum);测试一个信号是否属于一个信号集sigset_tmy_sigs;sigemptyset(&my_sigs);sigaddset(&my_sigs,SIGINT);if(sigismember(&my_sigs,SIGINT))puts(“hassigint/n”):if(sigismember(&my_sigs,SIGPIPE))puts(“hassigpipe/n”);设置信号操作<signal.h>structsigaction{viod(*sa_handler)();//信号处理函数指针可为SIG_DEF/SIG_IGNsigset_tsa_mask;//掩码值intsa_flags;//置0};intsigaction(intsignum,//信号conststructsigaction*act;//注册信号结构structsigaction*oldact//用于返回已注册的信号结构);返回已有信号操作:structsigactionsa_old;sigaction(SIGINT,0,&sa_old);例:报告SIGINT的当前设置structsigactionsa_old;sigaction(SIGINT,0,&sa_old);if(sa_old.sa_handler==SIG_DEF)puts(“SIG_DEF”):elseif(sa_old.sa_handler==SIG_IGN)puts(“SIG_IGN”);elseprintf(“sa_handler=0x%081X;/n”,(long)sa_old.sa_handler);例:#include<signal.h>#include<unistd.h>#include<stdio.h>staticintcount=0;voidhandler(intsigno){signal(SIGINT,handler);count++;printf(“GetSIGINT:%d/n”,count);}intmain(void){structsigactionsa_old;structsigactionsa_new;sa_new.sa_handler=handler;sigemptyset(&sa_new.sa_mask);sa_new.sa_flags=0;sigaction(SIGINT,&sa_new,&sa_old);while(count<2){puts(“WaitingforSIGINT…/n”);sleep(2);}sigaction(SIGINT,&sa_old,0);//restoresignalactionsputs(“end/n”);return0;}阻塞信号intsigpromask(inthow,constsigset_t*set,sigset_t*oldset);how:SIG_BLOCK指定的集合表明要阻塞(禁用)附加的信号SIG_UNBLOCK指定的集合表明信号将变为未阻塞态(启用态)SIG_SETMASK指定的集合替换当前的掩码说明:SIG_BLOCK/SIG_UNBLOCK宏修改了当前的信号掩码SIG_SETMASK宏允许调用程序完全替换当前的信号掩码例:如何阻塞SIGINT和SIGPIPE信号的接收sigset_tblk;//signalstoblocksigset_tsigsv;//savedsignalmasksigemptyset(&blk);//clearsetsigaddset(&blk,SIGINT);//addSIGINTsigaddset(&blk,SIGPIPE);//addSIGPIPEsigpromask(SIG_BLOCK,&blk,&sigsv);//blocksigs//criticalcodeheresigpromask(SIG_SETMASK,&sigsv,0);//restoremask获得等待状态的信号intsigpending(sigset_t*set);将等待信号的集合复制到set参数提供的集合中例:假定已阻塞SIGPIPE信号说明了如何测试同一信号是否处理等待状态sigset_tpendg;//pendingsignalsetsigpending(&pendg);//inquireofpendingsignalsif(sigismember(&pendg,SIGPIPE))puts(“SIGPIPEispending.”);唤醒信号,解除信号的阻塞intsigsuspend(constsigset_t*mask);临时使用mask参数中提供的信号掩码然后等待信号出现例:假定已阻塞SIGPIPE信号sigset_tpendg;sigset_tnotpipe;sigfillset(&notpipe);sigdelset(&notpipe,SIGPIPE);sigpending(&pendg);if(sigismember(&pendg,SIGPIPE))sigsuspend(&notpipe);调用sigsuspend时就会临时解除SIGPIPE信号的阻塞,并允许处理信号,然而,当信号处理函数返回时就会恢复原来的信号掩码.计时器unsignedintalarm(unsignedintseconds);创建计时器,在指定的时间到了之后就会唤醒SIGALRM信号如果在唤醒SIGALRM信号之前调用了alarm就会取消当前计时器并启动新的计时器给alarm指定0就会取消进行中的计时器每个进程只能有一个alarm计时器例:#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>//sinalcatcherstaticvoidcatch_sig(intsigno){if(signo==SIGINT){alarm(0);//cancelthetimerputs(“catchsigint/n”);}elseif(signo==SIGALRM)puts(“catchsigalrm/n”);}intmain(void){sigset_tsigs;structsigactionsa_old,sa_new;sa_new.sa_handler=catch_sig;sigemptyset(&sa_new.sa_mask);sigaddset(&sa_new.sa_mask,SIGINT);sigaddset(&sa_new.sa_mask,SiGALRM);sa_new.sa_flags=0;sigaction(SIGINT,&sa_new,&sa_old);sigaction(SIGALRM,&sa_new,0);sigfillset(&sigs,SIGINT);sigfillset(&sigs,SIGALRM);puts(“youhave3secondstosigint:/n”);alarm(3);sigsuspend(&sigs);//waitforsigintorsigalrmputs(“done/n”);return0;}唤醒信号<signal.h><sys/types.h>intkill(pid_tpid,intsig);唤醒指定进程中的指定信号例如在自己进程中唤醒SIGUSR1信号kill(getpid(),SIGUSR1);sig为0时,kill允许进程检查pid进程是否存在如:pid_tPID=1234;if(kill(PID,0)==-1){if(errno==ESRCH)puts(“process1234isnotexecuting./n”);elseperror(“kill”);}elseputs(“process1234isexecuting/n”);有效的I/O调度当进行I/O操作时如果读或写得不到请求,进程就会进入睡眠状态等待条件达到要求.解决方案:当不能完成I/O操作时系统调用返回一个错误,指明此时它没有成功,这就是非阻塞的I/O.1.在非阻塞模式下打开文件<fcntl.h>intopen(constchar*path,intflags,…);指定flags时让它包含O_NONBLOCK标志2.设置非阻塞模式<fcntl.h>intfcntl(intfd,intcmd,…);cmd取值:F_GETFL获得标志F_SETFL设置标志例:intfd,fl;f1=fcntl(fd,F_GETFL,0);if(f1==-1){perror(“fcntl(F_GETFL)”);exit(1);}if(fcntl(fd,F_SETFL,f1|O_NONBLOCK)==-1){perror(“fcntl(F_SETFL)”);exit(1);}例:在非阻塞模式下读取FIFO的程序#include<stdio.h>#include<unistd.h>#include<fcntl.h>#include<errno.h>intmain(void){intz;intfd;charbuf[256];fd=open(“./fifo”,O_RDWR|O_NONBLOCK);if(fd==-1){perror(“open”);exit(1);}while((z=read(fd,buf,sizeof(buf))==-1&&errno==EAGAIN);if(z>=0){buf[z]=0;printf(“GotInput:%s/n”,buf);}elseperror(“read”);return0;}I/O调度函数为了让核心知道什么唤醒进程进行I/O操作,进程就一定要注册它感兴趣的I/O事件文件描述符集合以及它们的宏<sys/types.h>FD_ZERO(fd_set*set);FD_SET(intfd,fd_set*set);FD_CLR(intfd,fd_set*set);intFD_ISSET(intfd,fd_set*set);FD_SETSIZE在使用文件描述符集合之前一定要先初始化它:fd_setfdset1;FD_ZERO(&fdset1);由FD_ZERO设置文件描述符的初始值,能够使它包含空集合.集合中最大序号的文件描述符是FD_SETSIZE,超过该值宏行为未定义要想给集合添加一个文件描述符,可以使用FD_SET:intfd=1;FD_ZERO(&fdset1);FD_SET(fd,&fdset1);可以使用FD_CLR从集合中删除一个文件描述符:FD_CLR(fd,&fdset1);测试一个文件描述符是否属于一个集合:if(FD_ISSET(2,&fdset1)){puts(“Standarderror(unit2)ispartoffdset1”);}else{puts(“Standarderror(unit2)isnotinfdset1”);}timeval结构定义:作为select函数的一个重要参数<sys/time.h>structtimeval{longtv_sec;//secondslongtv_usec;//microseconds};例:把timeout定认为1.25秒structtimevaltimeout;timeout.tv_sec=1;//1秒timeout.tv_usec=250000;//250000豪秒=0.25秒,10^6select函数:<sys/types.h><sys/time.h><unistd.h>intselect(intnfds,//offiledescriptorsfd_set*readfds;//readdescriptorsetfd_set*writefds;//writedescriptorsetfd_set*exceptfds;//exceptiondescriptorsetstructtimeval*timeout//timeoutvalue); 我只愿,在你的理想和希望里能为你增加一点鼓励,

Linux—signal(usr mode application) 编程

相关文章:

你感兴趣的文章:

标签云: