linux信号通信


linux里面进程间通信的另外一种方式就是信号通信。信号通信属于软件中的。

linux有如下几个常用的信号:

SIGHUP:终端上发出的结束信号

SIGINT :来自键盘的终端信号(CTRL+C)

SIGQUIT:来自键盘的退出信号(CTRL +\)

SIGFPE:浮点异常信号

SIGKILL:该信号结束接收信号的进程

SIGALRM:进程的定时器到期,发送该信号

SIGTERM:kill发送出的信号

SIGCHLD:标识子进程停止或结束的信号

SIGSTOP:来自键盘(CTRL+Z)或调试程序的停止信号


接收方有三种动作来对待信号:

1.忽略:SIGKILL、SIGSTOP例外

2.捕捉:执行终端服务程序

3.执行系统默认动作:(1)abort(2)exit(3)ignore(4)stop(5)continue


kill() and raise() method           raise() method can send signals to the proc who invoke the raise method.

int kill(pid_t pid, int signo);

int raise(int signo);

返回值:成功,0;出错,-1.

对于kill里面的pid:pid>0:至指定pid proc;pid==0:至同进程组的其他proc;pid<0:至pid绝对值的proc。


[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <signal.h>  
  4. #include <sys/types.h>  
  5. #include <sys/wait.h>  
  6.   
  7. int main()  
  8. {  
  9.     pid_t pid;  
  10.     int ret;  
  11.     if((pid=fork())<0){  
  12.         perror("fork");  
  13.         exit(1);  
  14.     }  
  15.     if(pid == 0){  
  16.         raise(SIGSTOP);                      //向自身发送停止信号  
  17.         exit(0);  
  18.     }  
  19.     else{  
  20.         printf("pid=%d\n",pid);  
  21.         if((waitpid(pid,NULL,WNOHANG))==0){  
  22.             if((ret=kill(pid,SIGKILL))==0)  
  23.                 printf("kill %d\n",pid);  
  24.             else{  
  25.                 perror("kill");  
  26.             }  
  27.         }  
  28.     }  
  29. }  



alarm() and pause() method.

alarm() can set a timer, when the timer is time out, then a SIGALRM signal will be sent to it.

the default action is to terminate the proc.

#include <unistd.h>

unsigned int alarm (unsigned int seconds);


pause() makes the proc which invokes it suspended, until it captures a signal.

#include <unistd.h>

int pause(void);


[cpp]  view plain copy
  1. #include <unistd.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4.   
  5. int main()  
  6. {  
  7.         int ret;  
  8.         ret=alarm(5);  
  9.         pause();  
  10.         /*printf("I have been waken up.\n",ret);*/  
  11. }  


信号处理            signal()

void (*signal (int signo, void (*func));

返回:成功则为以前的信号处理配置,若出错则为SIG_ERR

func的值有三种:

(1)常数SIG_IGN

(2)常数SIG_DFL

(3)要调用的函数地址

[cpp]  view plain copy
  1. #include <signal.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. void my_func(int sign_no)  
  5. {  
  6.     if(sign_no==SIGINT)  
  7.         printf("I have get SIGINT\n");  
  8.     else if(sign_no==SIGQUIT)  
  9.         printf("I have get SIGQUIT\n");  
  10. }  
  11. int main()  
  12. {  
  13.     printf("Waiting for signal SIGINT or SIGQUIT \n ");  
  14.     signal(SIGINT, my_func);                                //注册SIGINT的处理函数,CTRL+C可以触发  
  15.     signal(SIGQUIT, my_func);                               //注册SIGQUIT的处理函数,CTRL+\可以触发  
  16.     pause();  
  17.     exit(0);  
  18. }  


信号集函数组 signal set数据类型

#include <signal.h>

int sigemptyset ( sigset_t *set);

int sigfillset(sigset_t *set);

int sigaddset( sigset_t *set , int signo);

int sigdelset ( sigset_t *set , int signo);

返回值:成功,0;出错,-1。

int sigismember ( const sigset_t *set , int signo );

检查信号是否在信号集中。

int sigaction ( int signo, const struct sigaction *act, struct sigaction *oact);

检查或修改与指定信号相关的处理动作。

其中结构体参数 sigaction :

[cpp]  view plain copy
  1. struct  sigaction{  
  2.      void (*sa_handler)(int signo);  
  3.      sigset_t sa_mask;  
  4.      int sa_flags;  
  5.      void (*sa_restore);  
  6. }  

[cpp]  view plain copy
  1. #include <sys/types.h>  
  2. #include <unistd.h>  
  3. #include <signal.h>  
  4. #include <stdio.h>  
  5. #include <stdlib.h>  
  6.   
  7. void my_func(int signum)  
  8. {  
  9.     printf("If you want to quit,please try SIGQUIT\n");  
  10. }  
  11. int main()  
  12. {  
  13.     sigset_t set,pendset;  
  14.     struct sigaction action1,action2;  
  15.     if(sigemptyset(&set)<0)                       //empty the set  
  16.         perror("sigemptyset");                  
  17.     if(sigaddset(&set,SIGQUIT)<0)                 //add SIGQUIT signal  
  18.         perror("sigaddset");  
  19.     if(sigaddset(&set,SIGINT)<0)                  //add SIGINT signal  
  20.         perror("sigaddset");  
  21.     if(sigprocmask(SIG_BLOCK,&set,NULL)<0)        //阻塞中断  
  22.         perror("sigprocmask");  
  23.     else  
  24.     {  
  25.         printf("blocked\n");  
  26.         sleep(5);  
  27.     }  
  28.     if(sigprocmask(SIG_UNBLOCK,&set,NULL)<0)       //取消阻塞  
  29.         perror("sigprocmask");  
  30.     else  
  31.         printf("unblock\n");  
  32.     while(1){                                      //进入死循环,不断询问是否有SIGINT OR SIGQUIT信号。CTRL+C:SIGINT,CTRL+\:SIGQUIT  
  33.         if(sigismember(&set,SIGINT)){  
  34.             sigemptyset(&action1.sa_mask);  
  35.             action1.sa_handler=my_func;  
  36.             sigaction(SIGINT,&action1,NULL);  
  37.         }else if(sigismember(&set,SIGQUIT)){  
  38.             sigemptyset(&action2.sa_mask);  
  39.             action2.sa_handler = SIG_DFL;  
  40.             sigaction(SIGTERM,&action2,NULL);  
  41.         }  
  42.     }  
  43. }  

守护进程

特点:生存期长;后台运行;系统引导时就装入,系统关闭时才终止

ps -e 中看到的以d结尾的进程即守护进程(daemon),终端名称为?号。

所有daemon均以超级用户的优先级运行

除了update外,所有的daemon process都是进程组的首进程

所有daemon process 的parent process 都是init process.


(1)create sub proc, terminate parent proc

(2)invoke setsid

(3)change current dir to /

(4)reset 文件权限掩码

(5)close the unneeded file descriptor


[cpp]  view plain copy
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include<string.h>  
  4. #include<fcntl.h>  
  5. #include<sys/types.h>  
  6. #include<unistd.h>  
  7. #include<sys/wait.h>  
  8. #include<syslog.h>  
  9. #define MAXFILE 65535  
  10. int main()  
  11. {  
  12.     pid_t pc,sid;  
  13.     int i,fd,len;  
  14.     char *buf="This is a Dameon\n";  
  15.     len =strlen(buf);  
  16.     pc=fork();                                         //create sub process  
  17.     if(pc<0)  
  18.     {  
  19.         printf("error fork\n");  
  20.         exit(1);  
  21.     }  
  22.     else if(pc>0)                                      //terminate parent process  
  23.         exit(0);  
  24.           
  25.     setsid();                       //1.脱离会话组;2.脱离进程组;3.脱离控制终端,变为后台进程  
  26.     chidir("/");                    //改变目录  
  27.     umask(0);                       //对所有权限开放  
  28.     for(i=0;i<MAXFILE;i++)          //关闭所有不需要的文件描述符  
  29.         close(i);  
  30.     if((fd=open("/tmp/daemon.log",O_CREATE | O_WRONLY | O_APPEND, 0600))<0)     
  31.     {  
  32.         perror("open");  
  33.         exit(1);  
  34.     }  
  35.     while(1)  
  36.     {  
  37.           
  38.         write(fd, buf, len+1);        //写文件  
  39.         sleep(2);                     //每两秒写一次  
  40.     }  
  41.     close(fd);  
  42. }  


daemon的出错管理

通过syslog服务,将错误信息写到/var/log/message

openlog();

syslog():向日志文件里写入message

closelog();


#include <syslog.h>

void openlog( char *ident, int option, int facility );

ident: 要向每个消息加入的字符串,通常为程序名称

option: LOG_CONS, LOG_NDELAY, LOG_PERROR, LOG_PID


[cpp]  view plain copy
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include<string.h>  
  4. #include<fcntl.h>  
  5. #include<sys/types.h>  
  6. #include<unistd.h>  
  7. #include<sys/wait.h>  
  8. #include<syslog.h>  
  9.            
  10. #define MAXFILE 65535  
  11. int main()  
  12. {  
  13.     pid_t pc,sid;  
  14.     int i,fd,len;  
  15.     char *buf="This is a Dameon\n";  
  16.     len =strlen(buf);  
  17.     pc=fork();  
  18.     if(pc<0)  
  19.     {  
  20.         printf("error fork\n");  
  21.         exit(1);  
  22.     }  
  23.     else if(pc>0)  
  24.         exit(0);  
  25.     openlog("demo_update",LOG_PID, LOG_DAEMON);  
  26.     if((sid=setsid())<0)  
  27.     {  
  28.         syslog(LOG_ERR, "%s\n""setsid");  
  29.         exit(1);  
  30.     }  
  31.     if((sid=chdir("/"))<0)  
  32.     {  
  33.         syslog(LOG_ERR, "%s\n""chdir");  
  34.         exit(1);  
  35.     }  
  36.     umask(0);  
  37.     for(i=0;i<MAXFILE;i++)  
  38.         close(i);  
  39.     if((fd=open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND, 0600))<0)  
  40.     {  
  41.         syslog(LOG_ERR, "open");  
  42.         exit(1);  
  43.     }  
  44.     while(1)  
  45.     {  
  46.         write(fd, buf, len+1);  
  47.         sleep(10);  
  48.     }  
  49.     close(fd);  
  50.     closelog();  
  51.     exit(0);  
  52. }  




你可能感兴趣的:(入门,信号通信,LinuxUnix,示例教程)