Linux --sigaction舉例(改變信號默認操作)

環境 -- ubuntu64位
  1. 部分內核宏及函數對照
    /*signal number*/
    #define SIGHUP       1
    #define SIGINT       2
    #define SIGQUIT      3
    #define SIGILL       4
    #define SIGTRAP      5
    #define SIGABRT      6
    #define SIGIOT       6
    #define SIGBUS       7       
    #define SIGFPE       8
    #define SIGKILL      9
    #define SIGUSR1     10
    #define SIGSEGV     11
    #define SIGUSR2     12
    #define SIGPIPE     13
    #define SIGALRM     14
    #define SIGTERM     15
    #define SIGSTKFLT   16
    #define SIGCHLD     17
    #define SIGCONT     18
    #define SIGSTOP     19
    #define SIGTSTP     20
    #define SIGTTIN     21
    #define SIGTTOU     22
    #define SIGURG      23
    #define SIGXCPU     24
    #define SIGXFSZ     25
    #define SIGVTALRM   26
    #define SIGPROF     27
    #define SIGWINCH    28
    #define SIGIO       29
    #define SIGPOLL     SIGIO
    /*
    #define SIGLOST     29
    */
    #define SIGPWR      30
    #define SIGSYS      31
    #define SIGUNUSED   31
    /* 這些不應該被考慮 */
    #define SIGRTMIN    32
    #ifndef SIGRTMAX
    #define SIGRTMAX    _NSIG
    #endif
    
    /*int sa_flags*/
    #define SA_NOCLDSTOP    0x00000001
    #define SA_NOCLDWAIT    0x00000002
    #define SA_SIGINFO  0x00000004
    #define SA_ONSTACK  0x08000000
    #define SA_RESTART  0x10000000
    #define SA_NODEFER  0x40000000
    #define SA_RESETHAND    0x80000000
    
    #define SA_NOMASK   SA_NODEFER
    #define SA_ONESHOT  SA_RESETHAND
    
    /********************************/
    
    #define __BITS_PER_LONG 32
    
    #define _NSIG       64
    #define _NSIG_BPW   __BITS_PER_LONG       
    #define _NSIG_WORDS (_NSIG / _NSIG_BPW)
    /*sigset_t結構體*/
    typedef struct {
        unsigned long sig[_NSIG_WORDS]; /*  unsigned long sig[2];*/
    } sigset_t;
    
    /*sigaction結構體*/
    struct sigaction {
        void     (*sa_handler)(int);
        void     (*sa_sigaction)(int, siginfo_t *, void *);
        sigset_t   sa_mask;
        int        sa_flags;
        void     (*sa_restorer)(void);
    };
    
    /*how值*/
    #ifndef SIG_BLOCK
    #define SIG_BLOCK          0    /* for blocking signals */
    #endif
    #ifndef SIG_UNBLOCK
    #define SIG_UNBLOCK        1    /* for unblocking signals */
    #endif
    #ifndef SIG_SETMASK                                                
    #define SIG_SETMASK        2    /* for setting the signal mask */
    #endif
    
    /*handler提供的三種信號處理方式*/
    #define SIG_DFL ((__sighandler_t)0) /* 系統默認處理信號 */
    #define SIG_IGN ((__sighandler_t)1) /* 忽略該信號 */
    #define SIG_ERR ((__sighandler_t)-1)    /* 從信號返回錯誤 */
    
    /* 標準文件描述符  */
    #define STDIN_FILENO    0   /* Standard input.  */       
    #define STDOUT_FILENO   1   /* Standard output.  */
    #define STDERR_FILENO   2   /* Standard error output.  */
    
    	```
    
  2. 例子:
    /*1.部分信號處理舉例*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    
    /**
     * 函數名:sa_quit_handler
     * 描述:  用戶自定義SIGQUIT、SIGTSTP信號處理函數
     * 參數:  int signo -- 響應的信號
     * 返回值:nonu
     */
    void
    sa_user_handler(int signo){
    	
    	if(SIGQUIT == signo){		
    		fprintf(stderr, "rec: SIGQUIT\n");
    	}else if(SIGTSTP == signo){
    		fprintf(stderr, "rec: SIGTSTP\n");
    	}
    	
    }
    /*ctrl + z : 從鍵盤發送SIGTSTP信號給進程,暫停進程*/
    /*ctrl + \ : 從鍵盤發送SIGQUIT信號給進程,進程退出*/
    /*ctrl + c : 終止進程*/
    int
    main(void){
    	
    	struct sigaction act;
    	sigset_t register_mask;
    	sigemptyset(&register_mask); //清空sigset_t結構體
    	sigaddset(&register_mask, SIGQUIT|SIGTSTP); /*添加要阻塞的信號*/
    	
    	sigprocmask(SIG_BLOCK, &act.sa_mask, NULL); /*註冊信號處理函數前阻塞SIGQUIT、SIGTSTP信號*/
    	
    	/*註冊SIGQUIT信號處理函數部分*/
    	sigemptyset(&act.sa_mask); //清空sa_mask結構體成員
    	sigaddset(&act.sa_mask, SIGTSTP); /*在處理SIGQUIT信號程序中阻塞SIGTSTP信號*/
    	act.sa_handler=sa_user_handler;
    	act.sa_flags=SA_RESTART; //被信號中斷的系統調用會自行重啓
    	sigaction(SIGQUIT, &act, NULL); //註冊SIGQUIT信號處理函數
    
    	/*註冊SIGTSTP信號處理函數部分*/
    	sigemptyset(&act.sa_mask); //清空sa_mask結構體成員
    	sigaddset(&act.sa_mask, SIGQUIT); /*在處理SIGTSTP信號程序中阻塞SIGQUIT信號*/
    	act.sa_handler=sa_user_handler;
    	act.sa_flags=SA_RESTART; //被信號中斷的系統調用會自行重啓
    	sigaction(SIGTSTP, &act, NULL); //註冊SIGTSTP信號處理函數
    	
    	sigprocmask(SIG_UNBLOCK, &register_mask, NULL); /*註冊信號處理完成後解除阻塞SIGQUIT、SIGTSTP信號*/
    	
    	while(1);
    	return 0;
    }
    
    /*2.子進程不產生殭屍進程的方法*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <string.h>
    	
    #define handle_error(msg) \
    	do { perror(msg); exit(EXIT_FAILURE); } while (0) 
    /**
     * 函數名:sa_quit_handler
     * 描述:  用戶自定義SIGQUIT、SIGTSTP信號處理函數
     * 參數:  int signo -- 響應的信號
     * 返回值:nonu
     */
    void 
    sa_user_handler(int signo){
    /**
     *linux中,使用SA_NOPOSIX標誌下,POSIX.1不指定在子進程終止時是否生成SIGCHLD信號,
     * 在這個例子中是會生成一個SIGCHLD信號;在其他一些實現中,則不是這樣。
     */
    	if(SIGCHLD == signo){		
    		fprintf(stderr, "rec: SIGCHLD\n");
    	}
    }
    /*ctrl + z : 從鍵盤發送SIGTSTP信號給進程,暫停進程*/
    /*ctrl + \ : 從鍵盤發送SIGQUIT信號給進程,進程退出*/
    /*ctrl + c : 終止進程*/
    int
    main(void){
    	
    	struct sigaction act;
    	sigset_t register_mask;
    	pid_t ret;
    	
    	if((ret=fork())==-1){
    		handle_error("fork");
    	}
    	if(0==ret){ /*在子進程中*/
    	
    		 write(STDERR_FILENO, (char *)"In child!\n", strlen("In child!\n"));	
    		 sleep(3);
    		 write(STDOUT_FILENO, (char *)"child exit!\n", strlen("child exit\n!"));	
    		 
    	}else{ /*在父進程中*/
    	
    		write(STDOUT_FILENO, (char *)"In parent!\n", strlen("In parent\n!"));	
    		sigemptyset(&register_mask); //清空sigset_t結構體
    		sigaddset(&register_mask, SIGQUIT|SIGTSTP); /*添加要阻塞的信號*/
    		
    		sigprocmask(SIG_BLOCK, &act.sa_mask, NULL); 
    		/*註冊信號處理函數前阻塞SIGCHLD、SIGQUIT、SIGTSTP信號*/
    		
    		/*註冊SIGQUIT信號處理函數部分*/
    		sigemptyset(&act.sa_mask); //清空sa_mask結構體成員
    		sigaddset(&act.sa_mask, SIGQUIT|SIGINT); /*在處理SIGCHLD信號程序中阻塞SIGQUIT、SIGINT信號*/
    		act.sa_handler=sa_user_handler;
    		act.sa_flags=SA_NOCLDWAIT|SA_RESTART; 
    		/*被信號中斷的系統調用會自行重啓,子進程結束後不通知父進程,由init釋放子進程資源*/
    		sigaction(SIGCHLD, &act, NULL); //註冊SIGCHLD信號處理函數
    		
    		sigprocmask(SIG_UNBLOCK, &register_mask, NULL); 
    		/*註冊信號處理完成後解除阻塞SIGCHLD、SIGQUIT、SIGTSTP信號*/
    		while(1);
    		
    	}
    	
    	return 0;
    }	
    
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章