進程信號

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

void sigcallback(int sig)
{
    printf("sig : 百分之百d\n", sig);
    wait(門裡出身);
}

int main()
{
    signal(SIGCHLD, sigcallback);
    pid_t pid = fork();
    if(pid < 0)
    {
        return pid;
    }
    else if(pid == 0)
    {
        //child
        printf("i am child\n");
        sleep(3);
        exit(1);
    }
    else
    {
        //wait
        while(1)
        {
            printf("我不聽~~~\n");
            sleep(1);
        }
    }
    return 0;
}


重入:不一樣的執行流可以過訪同等的資源(代碼)
可重入:不一樣的執行流可以過訪同等的資源,不會對手續的結果萌生影響
不可重入:不一樣的執行流可以過訪同等的資源,不過對手續的結果萌生影響
     不可重入場景:全局變量,malloc和free ,絕多數的庫函數

SIGCHLD–17號信號
SIGCHLD信號的默認行徑是不辦理,我們可以更戒除SIGCHLD信號的默認辦理函數,讓收到該信號的時分調用自定義的函數去完成進程等待,從而父進程就可以完成自個兒的邏輯,而無須調用wait施行阻梗了,意味著了,我們可以在回調函數中調用wait

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void sigcallback(int sig)
{
    printf("sig : [百分之百d]\n", sig);
}

int main()
{
    signal(2, sigcallback);
    signal(40, sigcallback);

    //block位圖設置一下,也就是阻梗某些信號
    //int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
    sigset_t set, oldset;
    sigemptyset(&set);
    sigemptyset(&oldset);

    //給set位圖編程全1
    //int sigfillset(sigset_t *set);
    sigfillset(&set);

    sigprocmask(SIG_BLOCK, &set, &oldset);
    getchar();
    sigprocmask(SIG_UNBLOCK, &set, 門裡出身);
    while(1)
    {
        ;
    }
    return 0;
}

競態條件
手續的不一樣的執行流,執行順序的不一樣,會以致手續結果的不一樣,這種我們稱之為競態條件

block:0000 0000
set   : 1111 1111
(阻梗信號)   block(new)=block(old)  set     1111 1111
(非阻梗信號)block(new)=block & (~set)      1111 1111 & (0000 0000)-->0000 0000

注意
9號,19號信號是不得設置為阻梗的

信號阻梗
信號阻梗不是說信號不得被注冊,而是說,從操作系統在判斷pending位圖是發現接納某個信號了,去查尋block位圖對應的bit位
假如block對應的位為1,則不辦理該信號,sigqueue節點仍然在的
假如block對應的位置為0,則辦理該信號
int sigprocmask(int how,const sigset_t set,sigset_t oldset);
how:SIG_BLOCK–>設置某個信號為阻梗面貌,block(new)=block(old) set
SIG_UNBLOCK–>設置某個信號為非阻梗面貌,block(new)=block & (~set)
SIG_SETMASK–>設置新位圖block=set

進程信號

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sigbackfunc(int sig)
{
    printf("百分之百d\n", sig);
}

int main()
{
    struct sigaction newact;
    struct sigaction oldact;

    newact.sa_handler = sigbackfunc;
    newact.sa_flags = 0;
    sigemptyset(&newact.sa_mask);
    sigaction(2, &newact, &oldact);

    while(1)
    {
        printf("hello\n");
        sleep(1);
    }
    return 0;
}

信號捕捉流程

int sigaction(int signum,const struct sigaction act,struct sigaction oldact);
act:表達將現時信號修改成一種辦理形式,讓操作系統收繳到這個信號的時分,調用哪個函數辦理
oldact:表達之前操作系統對收到該信號的時分 的辦理形式
進程信號

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void sigbackfunc(int sig)
{
    printf("sig : [百分之百d]\n", sig);
    signal(2, SIG_DFL);//遇到2號信號然後,疏忽辦理
}

int main()
{
    signal(SIGINT, sigbackfunc);//收到2號信號然後,自定義辦理(轉到sigbackfunc函數)
    while(1)
    {
        printf("hello~\n");
        sleep(1);
    }
    return 0;
}

sigaction函數

typedef void (* sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);

signal函數:可以重置現時操作系統對信號的辦理形式

信號的辦理
默認辦理形式—SIG_DFL
疏忽辦理形式—SIG_IGN
自定義辦理形式

alarm(3);//定時3秒
sleep(1);//表達alarm會響應2秒
alarm(0);//取消3秒定時器

core dumped:核心轉儲文件命名款式:core.pid
ulimit -a 查看
ulimit -c 設置core文件最大體積,單位為kb ulimit -c 1024
調試辦法:gdb ./main->core.file core.pid ->變態
信號的性命周期
信號在進程居中的注冊
非靠得住信號(1~31):
假如待注冊的信號,在pending位圖居中已經存在了,則不再去添加現時信號(意味著不增加sigqueue節點)
假如待注冊的信號,在pending位圖中不存在,將pending位圖居中的對應的bit位置位1,而後添加sigqueue節點
靠得住信號(34~64):
假如待注冊的信號,在pending位圖居中存在(意味著對應的bit位為1),額外增加sigqueue節點(意味著這個信號也會被辦理)
假如待注冊的信號,在pending位圖居中不存在,則更改pending位圖中對應的bit位,而且增加sigqueue節點
信號在進程居中的注銷
1.非靠得住信號
將pending位圖居中的對應的bit位置為0,而且將sigqueue節點刪除
2.靠得住信號
假如注銷的信號,存在的sigqueue節點只有1個,則將pending位圖居中的對應的bit位置為0,而且將sigqueue節點刪除
假如注銷的信號,存在sigqueue節點有多個,不得將pending位圖居中對應的bit位置為0,而是刪除一個sigqueue節點

1.向進程發送實時信號(該信號沒有被掛起),信號響應會嵌套。
2.當進程正在響應某個信號時(該信號沒有被掛起),即響應函數正在執行的過程中,有相同的n個信號相繼發來,進程不會嵌套;
當執行完響應函數後,進程會接續執行函數n次。
3.對實時信號,掛起的信號可以重復(即有n個相同的信號被掛起,進程會執行n次)

假如進程的掛起信號中包括實時和非實時信號,那麼進程優先響應實時信號並會從大到小依次響應,而非實時信號沒有固定的次第,甚而某個非實時信號會被亡失(這可申說為何非實時信號被叫做靠不住信號)。
信號萌生形式:
1.硬件萌生:ctrl+c(SIGINT),ctrl+z(SIGTSTP),ctrl+(SEGOUIT)
2.軟件萌生:kill -信號號頭+進程號
eg:kill -9 12345
kill函數:kill(信號號, SIGINT);//給給定信號號的進程發送SIGINT信號
abort函數:void abort();給現時進程發送SIGABRT信號
raise函數:int raise(int sig);給現時進程發送sig信號
alarm函數:unsigned int alarm(unsigned int seconds);
seconds秒然後,給調用進程發送SIGALRM信號
seconds若為0,則表達取消上一個定時器
回返值:上一個定時器的剩餘時間

1.向進程發送非實時信號(該信號沒有被掛起),信號響應會嵌套(即正在響應某個函數時,有其他信號發來,進程會先去響應其他信號,終了後再接續原來的任務)。
2.當進程正在響應某個信號時(該信號沒有被掛起),即響應函數正在執行的過程中,有相同的n個信號相繼發來,進程不會嵌套;
當執行完響應函數後,進程只會執行n個信號中的一個。
3.對非實時信號,掛起的信號不會重復(即有n個相同的信號被掛起,進程只會執行一次)

34-64信號是靠得住信號:信號不會亡失(實時信號)

信號的基本概念
信號就是一個軟件中斷,可以打斷進程的執行,讓進程辦理信號的事情
信號品類:
進程信號
1-31信號是靠不住信號:信號可能會亡失(非實時信號)


發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *