linux多進程——進程組與會話、守護進程、信號通信 .

[+]
  1. killraise 發信號一些相關知識可以參考 Linux 信號通信
  2. pause 將進程掛起直到捕捉到信號爲止
  3. 舉例1
 一、進程組與會話

    進程組:是一個或多個進程的集合。可以調用 getpgid(0) 或 getpgrp() 來得到。進程組ID爲組長的進程ID。只要進程組中有一個進程存在,進程組就存在,與組長進程是否終止無關。調用 setpgid() 加入一個現有的進程組或創建一個新的進程組。

 

    會話:一個或多個進程組的集合

 

 

       可以用 setsid() 建立新會話,則該進程會變成新會話的首進程,同時成爲一個新進程組的組長進程,該進程沒有控制終端

 

二、守護進程

    守護進程的特點:沒有終端的限制,不受用戶、終端或其它的變化而受到影響。

   

 創建守護進程的步驟:

 

    出錯處理:因爲守護進程不依賴於終端,所以出錯信息是不能用 printf 滴,這..... 怎麼辦?莫怕,用 syslog() 就能搞定~

 

     用系統日誌就要調用三個函數:openlog()、syslog()、closelog()  系統日誌存於 /var/log/messages

 

舉例:

  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3. #include<sys/types.h>   
  4. #include<syslog.h>   
  5.   
  6. int main(){  
  7.     pid_t pid,s;  
  8.     int i;  
  9.     char *buff="Daemon Test!\n";  
  10.     if((pid = fork())<0){  
  11.         printf("fork error!\n");  
  12.         exit(1);  
  13.     }else if(pid> 0){  
  14.         exit(0);  
  15.     }  
  16.       
  17.     //第一個參數爲在消息之前加入的字符串,第二個參數在每個消息中包含進程的ID,第三個參數指定程序發送的消息類型   
  18.     openlog("daemon_testlog",LOG_PID,LOG_DAEMON);     
  19.     if((s=setsid())<0){  
  20.         //第一個參數爲參數類型,第二個參數爲信息字符串   
  21.         syslog(LOG_ERR,"%s\n","setsid error!");     
  22.     }  
  23.     chdir("/");  
  24.     umask(0);  
  25.     for(i=0;i<getdtablesize();i++){   //關閉文件描述   
  26.         close(i);  
  27.     }  
  28.     while(1){  
  29.         syslog(LOG_INFO,"%s\n",buff);  
  30.         sleep(10);  
  31.     }  
  32.     closelog();  
  33.     return 0;  
  34. }  
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<syslog.h>

int main(){
    pid_t pid,s;
    int i;
    char *buff="Daemon Test!\n";
    if((pid = fork())<0){
        printf("fork error!\n");
        exit(1);
    }else if(pid> 0){
        exit(0);
    }
    
    //第一個參數爲在消息之前加入的字符串,第二個參數在每個消息中包含進程的ID,第三個參數指定程序發送的消息類型
    openlog("daemon_testlog",LOG_PID,LOG_DAEMON);   
    if((s=setsid())<0){
        //第一個參數爲參數類型,第二個參數爲信息字符串
        syslog(LOG_ERR,"%s\n","setsid error!");   
    }
    chdir("/");
    umask(0);
    for(i=0;i<getdtablesize();i++){   //關閉文件描述
        close(i);
    }
    while(1){
        syslog(LOG_INFO,"%s\n",buff);
        sleep(10);
    }
    closelog();
    return 0;
}

 

 

三、信號

 

    Linux對每種信號都制定了默認的操作。捕捉到信號可以採用默認的操作、可以忽略(SIGKILL 與 SIGSTOP除外)、也可以執行相應的自定義處理函數。

 

kill()、raise() 發信號。一些相關知識可以參考 Linux 信號通信  

pause() 將進程掛起直到捕捉到信號爲止。

 

舉例1:

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <signal.h>   
  4.   
  5. void my_func(int);  
  6.   
  7. int main() {  
  8.     printf("Wainting for signal: SIGINT/SIGQUIT...\n");  
  9.     signal(SIGINT,my_func);  
  10.     signal(SIGQUIT,my_func);  
  11.     pause();  
  12.     pause();  
  13.     exit(0);  
  14. }  
  15.   
  16. void my_func(int sign_no){  
  17.     if (sign_no==SIGINT) {  
  18.         printf("I got CTRL+C!\n");  
  19.     } else if (sign_no==SIGQUIT) {  
  20.         printf("I got CTRL+\\!\n");  
  21.     }   
  22. }  
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void my_func(int);

int main() {
	printf("Wainting for signal: SIGINT/SIGQUIT...\n");
	signal(SIGINT,my_func);
	signal(SIGQUIT,my_func);
	pause();
	pause();
	exit(0);
}

void my_func(int sign_no){
	if (sign_no==SIGINT) {
		printf("I got CTRL+C!\n");
	} else if (sign_no==SIGQUIT) {
		printf("I got CTRL+\\!\n");
	} 
}

舉例2: 

  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3. #include<sys/types.h>   
  4. #include<signal.h>   
  5.   
  6. int main(){  
  7.     pid_t pid;  
  8.     if((pid = fork())<0){  
  9.         printf("fork error!\n");  
  10.         exit(1);  
  11.     }else if(pid == 0){  
  12.         printf("Child process wait for singal....a\n");  
  13.         raise(SIGSTOP);     //子進程向自己發送一個消息,線程停止   
  14.         printf("Child is dead\n");    //此句不會打出來,因爲進程直接被kill了   
  15.     }else{  
  16.         sleep(10);  
  17.         kill(pid,SIGKILL);  
  18.         wait(NULL);  
  19.     }  
  20.     return 0;  
  21. }  
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<signal.h>

int main(){
    pid_t pid;
    if((pid = fork())<0){
        printf("fork error!\n");
        exit(1);
    }else if(pid == 0){
        printf("Child process wait for singal....a\n");
        raise(SIGSTOP);     //子進程向自己發送一個消息,線程停止
        printf("Child is dead\n");    //此句不會打出來,因爲進程直接被kill了
    }else{
        sleep(10);
        kill(pid,SIGKILL);
        wait(NULL);
    }
    return 0;
}

 

   alarm()  在進程中設置一個定時器,當時間到時,發出SIGALARM信號。一個進程只能有一個鬧鐘時間,新的將代替舊的。返回值爲新舊時間差值。

 

舉例:

  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3. #include<sys/types.h>   
  4. #include<signal.h>   
  5.   
  6. int main(){  
  7.     int ret=alarm(5);  
  8.     printf("alarm...%d\n",ret);  
  9.     sleep(3);  
  10.     ret=alarm(5);  
  11.   
  12.     printf("alarm...%d\n",ret);  
  13.     pause();  
  14.     printf("never show\n");  
  15.   
  16. }  
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<signal.h>

int main(){
    int ret=alarm(5);
    printf("alarm...%d\n",ret);
    sleep(3);
    ret=alarm(5);

    printf("alarm...%d\n",ret);
    pause();
    printf("never show\n");

}


程序運行結果爲:alarm...0    alarm....2  。 2爲相差時間,程序收到SIGALARM默認執行的操作爲終止線程。

 

sigaction()函數:signal()的高級版~

 

例子:

  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3. #include<sys/types.h>   
  4. #include<signal.h>   
  5.   
  6. void my_func(int);  
  7.   
  8.   
  9. int main(){  
  10.     struct sigaction sa,oldsa;  
  11.   
  12.     printf("waiting for SIGINT/SIGQUIT......\n");  
  13.     sa.sa_handler=my_func;         //設定處理函數   
  14.     sigemptyset(&sa.sa_mask);      //清空信號集合   
  15.     sa.sa_flags=0;                //對信號處理的選項一般設爲0   
  16.   
  17.     sigaction(SIGINT,&sa,&oldsa);     //oldsa爲保存舊的信號結構體   
  18.     sigaction(SIGQUIT,&sa,&oldsa);  
  19.   
  20.     pause();  
  21.     pause();  
  22.     pause();  
  23.     pause();  
  24.     pause();  
  25.     pause();  
  26.     pause();  
  27.   
  28. }  
  29.   
  30. void my_func(int sig){  
  31.     if(sig == SIGINT){  
  32.         printf("Receive CTRL+C!\n");  
  33.     }  
  34.     else if(sig == SIGQUIT){  
  35.         printf("Receive CTRL+\\!\n");  
  36.     }else  
  37.     printf("Receive Signal!\n");  
  38. }  
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<signal.h>

void my_func(int);


int main(){
    struct sigaction sa,oldsa;

    printf("waiting for SIGINT/SIGQUIT......\n");
    sa.sa_handler=my_func;         //設定處理函數
    sigemptyset(&sa.sa_mask);      //清空信號集合
    sa.sa_flags=0;                //對信號處理的選項一般設爲0

    sigaction(SIGINT,&sa,&oldsa);     //oldsa爲保存舊的信號結構體
    sigaction(SIGQUIT,&sa,&oldsa);

    pause();
    pause();
    pause();
    pause();
    pause();
    pause();
    pause();

}

void my_func(int sig){
    if(sig == SIGINT){
        printf("Receive CTRL+C!\n");
    }
    else if(sig == SIGQUIT){
        printf("Receive CTRL+\\!\n");
    }else
    printf("Receive Signal!\n");
}


信號集

 

 

  通常就是這個步驟。清空信號集->添加信號->設置信號屏蔽->定義信號處理

 

舉例:

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <signal.h>   
  4. #include <sys/types.h>   
  5. #include <unistd.h>   
  6.   
  7. void my_func(int);  
  8.   
  9. int main() {  
  10.     struct sigaction sa1,sa2;  
  11.     sigset_t set;  
  12.     //清空   
  13.     if (sigemptyset(&set)<0) {  
  14.     perror("sigemptyset");  
  15.     exit(1);  
  16.     }  
  17.     //添加信號        
  18.     if (sigaddset(&set,SIGINT)<0) {  
  19.     perror("sigaddset SIGINT");  
  20.     exit(1);  
  21.     }  
  22.     if (sigaddset(&set,SIGQUIT)<0) {  
  23.     perror("sigaddset SIGQUIT");  
  24.     exit(1);  
  25.     }  
  26.     //設置信號     
  27.     if (sigismember(&set,SIGINT)) {  
  28.     sa1.sa_handler=my_func;  
  29.     sigemptyset(&sa1.sa_mask);  
  30.     sa1.sa_flags=0;  
  31.     sigaction(SIGINT,&sa1,NULL);  
  32.     }  
  33.   
  34.     if (sigismember(&set,SIGQUIT)) {  
  35.     sa2.sa_handler=SIG_DFL;  
  36.     sigemptyset(&sa2.sa_mask);  
  37.     sa2.sa_flags=0;  
  38.     sigaction(SIGQUIT,&sa2,NULL);  
  39.     }  
  40.     //設置屏蔽字   
  41.     if (sigprocmask(SIG_BLOCK,&set,NULL)<0) {  
  42.     perror("sigprocmask");  
  43.     exit(1);  
  44.     } else {  
  45.     printf("Signal set is blocked!\n");  
  46.     }  
  47.     while(1){  
  48.         int c=getchar();  
  49.     if ((c=='u')||(c=='U'))  
  50.         break;  
  51.     }  
  52.     //解除屏蔽字   
  53.     if (sigprocmask(SIG_UNBLOCK,&set,NULL)<0) {  
  54.     perror("sigprocmask");  
  55.     exit(1);  
  56.     } else {  
  57.     printf("Signal set is unblocked!\n");  
  58.     }  
  59. }  
  60.   
  61. void my_func(int sig){  
  62.     if(sig == SIGINT){  
  63.     printf("Receive CTRL+C!\n");  
  64.     }  
  65.     else if(sig == SIGQUIT){  
  66.         printf("Receive CTRL+\\!\n");  
  67.     }else  
  68.     printf("Receive signal!\n");  
  69. }  
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

void my_func(int);

int main() {
    struct sigaction sa1,sa2;
    sigset_t set;
    //清空
    if (sigemptyset(&set)<0) {
	perror("sigemptyset");
	exit(1);
    }
    //添加信號     
    if (sigaddset(&set,SIGINT)<0) {
	perror("sigaddset SIGINT");
	exit(1);
    }
    if (sigaddset(&set,SIGQUIT)<0) {
	perror("sigaddset SIGQUIT");
	exit(1);
    }
    //設置信號	
    if (sigismember(&set,SIGINT)) {
	sa1.sa_handler=my_func;
	sigemptyset(&sa1.sa_mask);
	sa1.sa_flags=0;
	sigaction(SIGINT,&sa1,NULL);
    }

    if (sigismember(&set,SIGQUIT)) {
	sa2.sa_handler=SIG_DFL;
	sigemptyset(&sa2.sa_mask);
	sa2.sa_flags=0;
	sigaction(SIGQUIT,&sa2,NULL);
    }
    //設置屏蔽字
    if (sigprocmask(SIG_BLOCK,&set,NULL)<0) {
	perror("sigprocmask");
	exit(1);
    } else {
	printf("Signal set is blocked!\n");
    }
    while(1){
        int c=getchar();
	if ((c=='u')||(c=='U'))
		break;
    }
    //解除屏蔽字
    if (sigprocmask(SIG_UNBLOCK,&set,NULL)<0) {
	perror("sigprocmask");
	exit(1);
    } else {
	printf("Signal set is unblocked!\n");
    }
}

void my_func(int sig){
    if(sig == SIGINT){
    printf("Receive CTRL+C!\n");
    }
    else if(sig == SIGQUIT){
        printf("Receive CTRL+\\!\n");
    }else
    printf("Receive signal!\n");
}

 

 [注] 1、解鎖的瞬間即調用處理函數。2、內核只會保存一個同類的信號,其他的都被丟掉了。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章