感谢支持
我们一直在努力

Linux入门教程: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

  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.     pid_t pid; 
  9.     int ret; 
  10.     if((pid=fork())<0){ 
  11.         perror(“fork”); 
  12.         exit(1); 
  13.     } 
  14.     if(pid == 0){ 
  15.         raise(SIGSTOP);                      //向自身发送停止信号  
  16.         exit(0); 
  17.     } 
  18.     else
  19.         printf(“pid=%d\n”,pid); 
  20.         if((waitpid(pid,NULL,WNOHANG))==0){ 
  21.             if((ret=kill(pid,SIGKILL))==0) 
  22.                 printf(“kill %d\n”,pid); 
  23.             else
  24.                 perror(“kill”); 
  25.             } 
  26.         } 
  27.     } 

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);



  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)要调用的函数地址



  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 :



  1. struct  sigaction{  

  2.      void (*sa_handler)(int signo);  

  3.      sigset_t sa_mask;  

  4.      int sa_flags;  

  5.      void (*sa_restore);  

  6. }  


  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



  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



  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. }  

赞(0) 打赏
转载请注明出处:服务器评测 » Linux入门教程:Linux信号通信
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏