天天看點

LinuxC:信号處理 alarm() 信号集操作函數 sigprocmask() sigpending() sigsuspend() SIGCHILD信号 實作sleep()

LinuxC:信号處理 alarm() 信号集操作函數 sigprocmask() sigpending() sigsuspend() SIGCHILD信号 實作sleep()
  • kill -l:Linux檢視目前系統有哪些信号

    man 7 signal:Linux檢視信号手冊

    ulimit -a:Linux指令可檢視core檔案大小(core file size)

    ulimit -c 1024:Linux指令設定core檔案大小為1024

    ulimit -c unlimited: 大小設定為無限制

  • Tern:終止目前程序

    Core:Tern并且Core Dump(産生core檔案)

    Ign:忽略信号

    Stop:停止(暫停)目前程序

    Cont:繼續執行之前Stop的程序

    SIGINT信号:例如鍵盤按下Ctrl+C

    信号遞達delivery:實際執行信号的處理動作

    信号未決pending:信号産生到遞達之間的狀态,例如程序阻塞時的狀态

  • kill指令是調用**kill()**函數實作的。成功傳回-,失敗傳回-1
  • alarm() 告訴核心幾秒後給目前程序發送SIGALRM信号
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
           
  • 信号集操作函數
#include <signal.h>

//以下4個函數 成功傳回0,失敗傳回-1
int sigemptyset(sigset_t *set); //清空信号集
int sigfillset(sigset_t *set); //初始化信号集
int sigaddset(sigset_t *set, int signo); //添加sign o信号
int sigdelset(sigset_t *set, int signo); //删除signo信号

//傳回1表示有此信号 傳回0表示沒有此信号 傳回-1表示出錯
int sigismember(const sigset_t *set, int signo); 
           
  • 信号屏蔽字:目前程序的阻塞信号集
#include <signal.h>

//讀取或更改程序的信号屏蔽字
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
           
  • 未決信号集 成功傳回1,出錯傳回-1
#include <signal.h>

//讀取目前程序的未決信号集
int sigpending(sigset_t *set);
           
  • 捕捉信号:信号的處理動作是使用者自定義函數,信号遞達時即調用此函數,例如sigaction() 更改信号
  • pause() sigsuspend():調用程序挂起直到有信号遞達 傳回值隻有-1

    隻有執行捕捉信号的函數才傳回-1,其餘沒有機會傳回,errno=EINTR

#include <unistd.h>
int pause();

#include <signal.h>
//除了有pause()的功能,還解決了競态條件,時序要求嚴格要用這個函數
int sigsuspend(const sigset_t *sigmask);
           
  • 實作sleep()
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>

void sig_alarm(int signo) {
    return ;
}

unsigned int mysleep(unsigned int sec) {
    struct sigaction newact, oldact;
    sigset_t newmask, oldmask, susmask; //信号屏蔽字

    newact.sa_handler = sig_alarm;
    newact.sa_flags = 0;
    sigemptyset(&newact.sa_mask);

    sigaction(SIGALRM, &newact, &oldact);

    //阻塞鬧鐘信号
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGALRM);
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);

    alarm(sec); //啟動鬧鐘

    susmask = oldmask;
    //删除alarm信号
    sigdelset(&susmask, SIGALRM);
    //挂起程式等信号到來 臨時設定susmask信号屏蔽字
    sigsuspend(&susmask);

    int unslept = alarm(0);
    sigaction(SIGALRM, &oldact, NULL);
    sigprocmask(SIG_SETMASK, &oldmask, NULL); //讀取或更改程序的信号屏蔽字

    return unslept;
}

int main() {
    return 0;
}
           

SIGCHILD信号

  • 子程序退出時會發此信号,此信号可自定義信号處理函數sigaction()
  • Linux下直接處理不産生僵屍程序的信号方法:

    父程序調用sigaction()将SIGCHILD信号的處理動作置為SIG_IGN。

    此時fork()出來的子程序在終止時會自動清理掉,不産生僵屍程序,也不會通知父程序。