日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,

發布時間:2024/9/27 编程问答 21 豆豆


1信號產生原因

2.進程處理信號行為

manpage里信號3中處理方式:

SIG_IGN

SIG_DFL??????????????????????????????????????????? 默認Term動作

a signal handling function

進程處理信號

A默認處理動作

term?? 中斷

core??? core(調試的時候產生)

gcc –g file.c

?? ?ulimit –c 1024

?? ?gdb a.out core

ign????? 忽略

stop???? 停止

cont???? 繼續

B忽略

C捕捉(用戶自定義處理函數)

3信號集處理函數

sigset_t為信號集,可sizeof(sigset_t)查看

將信號集里面的每位都置0

int sigemptyset(sigset_t *set)

將所有信號集都置1

int sigfillset(sigset_t *set)

添加一個信號,也就是將Block阻塞信號集里面的某一位置成1

int sigaddset(sigset_t *set, int signo)

將信號集中某一位取消置1

int sigdelset(sigset_t *set, int signo)

測試某個信號集中的信號是否為1

int sigismember(const sigset_t *set, intsigno)

4 PCB的信號集

信號在內核中的表示示意圖

如果在進程解除對某信號的阻塞之前這種信號產生過多次,將如何處理?POSIX.1

許系統遞送該信號一次或多次。Linux是這樣實現的:常規信號在遞達之前產生多次只

計一次,而實時信號在遞達之前產生多次可以依次放在一個隊列里。本章不討論實時信

號。從上圖來看,每個信號只有一個bit的未決標志,非01,不記錄該信號產生了多少

次,阻塞標志也是這樣表示的。因此,未決和阻塞標志可以用相同的數據類型sigset_t

來存儲,sigset_t稱為信號集,這個類型可以表示每個信號的“有效”或“無效”狀態,

在阻塞信號集中“有效”和“無效”的含義是該信號是否被阻塞,而在未決信號集中“有

效”和“無效”的含義是該信號是否處于未決狀態。

阻塞信號集也叫做當前進程的信號屏蔽字(Signal Mask),這里的“屏蔽”應該理解

為阻塞而不是忽略。

5sigprocmask

調用函數sigprocmask可以讀取或更改進程的信號屏蔽字。

依賴的頭文件:

#include <signal.h>

函數聲明:

*set是傳入的信號,*oset表示原來的信號集是什么,相當于是*set的一個備份

intsigprocmask(int how, const sigset_t *set, sigset_t *oset);?????????

返回值:若成功則為0,若出錯則為-1

如果oset是非空指針,則讀取進程的當前信號屏蔽字通過oset參數傳出。如果set是非空指針,則更改進程的信號屏蔽字,參數how指示如何更改。如果osetset都是非空指針,則先將原來的信號屏蔽字備份到oset里,然后根據sethow參數更改信號屏蔽字。假設當前的信號屏蔽字為mask,下表說明了how參數的可選值。

??? how參數的含義

SIG_BLOCK set包含了我們希望添加到當前信號屏蔽字的信號,相當于mask=mask|set

SIG_UNBLOCK set包含了我們希望從當前信號屏蔽字中解除阻塞的信號,相當于mask=mask&~set

SIG_SETMASK 設置當前信號屏蔽字為set所指向的值,相當于mask=set

6sigpending(未決打印信號)

#include<signal.h>

int sigpending(sigset_t *set)

sigpending讀取當前進程的未決信號集,通過set參數傳出。調用成功則返回0,出錯則

返回-1

6案例說明:

運行結果:

程序運行時,每秒鐘把各信號的未決狀態打印一遍,由于我們阻塞了SIGINT信號,按Ctrl-C將會使SIGINT信號處于未決狀態,按Ctrl-\仍然可以終止程序,因為SIGQUIT信號沒有阻塞。

這時按Ctrl+\結束。

7信號捕捉設定

8.sigaction

#include <signal.h>

int sigaction(int signum, const structsigaction *act,

struct sigaction *oldact);

?

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

};

sa_handler:早期的捕捉函數

sa_sigaction : 新添加的捕捉函數,可以傳參,sa_handler互斥,兩者通過sa_flags選擇采用哪種捕捉函數

sa_mask : 在執行捕捉函數時,設置阻塞其它信號,sa_mask| 進程阻塞信號集,退出捕捉函數后,還原回原有的阻塞信號集

sa_flags : SA_SIGINFO 或者0

sa_restorer:保留,已過時。

案例說明:

#include<stdio.h>

#include<signal.h>

#include<unistd.h>

?

void do_sig(int num)

{

????int n = 5;

????printf("I am do_sig\n");

????printf("num = %d\n",num);

????while(n--)

????{

?? ??????printf("num = %d\n",num);

????????sleep(1);

????}

}

?

int main(void)

{

????struct sigaction act;

????act.sa_handler = do_sig;

????//act.sa_handler = SIG_DFL;

????//act.sa_handler = SIG_IGN;

????sigemptyset(&act.sa_mask);

????sigaddset(&act.sa_mask,SIGQUIT);

????act.sa_flags = 0;

?

????sigaction(SIGINT,&act,NULL);

?

??? ?while(1)

????{

????????printf("**********\n");

?????? sleep(1);

????}

????return 0;

}

9 C標準庫信號處理函數

typedef void (*sighandler_t)(int)

sighandler_t signal(int signum,sighandler_t handler)

int system(const char *command)

system的本質是:集合forkexecwait一體

10 可重入函數

A:不含全局變量和靜態變量是可重入函數的一個要素

B:可重入函數man? 7??signal

C:在信號捕捉函數里應可重入函數

例如:strtok就是一個不可重入函數,因為strtok內部維護了一個內部靜態指針,保存上一次切割到的位置,如果信號的捕捉函數中也去調用strtok函數,則會造成切割字符串混亂,應用strtok_r版本,r表示可重入。

11時序競態

int pause(void)

使調用進程掛起,直到有信號遞達,如果遞達信號是忽略,則繼續掛起

int sigsuspend(const sigset_t *mask)

以通過指定mask來臨時解除對某個信號的屏蔽,然后掛起等待,sigsuspend返回時,進程的信號屏蔽字恢復為原來的值

#include <unistd.h>

#include <signal.h>

#include <stdio.h>

void sig_alrm(int signo)

{

/* nothing to do */

}

unsigned int mysleep(unsigned int nsecs)

{

struct sigaction newact, oldact;

unsigned int unslept;

newact.sa_handler = sig_alrm;

sigemptyset(&newact.sa_mask);

newact.sa_flags = 0;

sigaction(SIGALRM, &newact, &oldact);

?

alarm(nsecs);

//alarm的時候,可能會轉到其它程序,這之后永遠都執行不到下面的這行,因為信號已經執行過了

pause();

?

unslept = alarm(0);

sigaction(SIGALRM, &oldact, NULL);

return unslept;

}

?

int main(void)

{

while(1){

mysleep(2);

printf("Two seconds passed\n");

}

return 0;

}

mysleep的改進版

#include<unistd.h>

#include<signal.h>

#include<stdio.h>

?

void sig_alrm(int signo)

{??

????/* nothing to do*/

}

?

unsigned int mysleep(unsigned int nsecs) {??

struct sigaction newact,oldact;

??? sigset_tnewmask,oldmask,suspmask;

??? unsigned int unslept;

??? /*set our handler,saveprevious information*/

??? newact.sa_handler =sig_alrm;

? ??sigemptyset(&newact.sa_mask);

??? newact.sa_flags = 0;

???sigaction(SIGALRM,&newact,&oldact);

??? /*block SIGALRM and savecurrent signal mask*/

??? sigemptyset(&newmask);

?sigaddset(&newmask,SIGALRM);

?sigprocmask(SIG_BLOCK,&newmask,&oldmask);

?? ???alarm(nsecs);

???suspmask = oldmask;

? /*make sure SIGALRM isn'tblocked*/

???sigdelset(&suspmask,SIGALRM);

? sigsuspend(&suspmask);/*waitfor any signal to be caught*/

??? /*some signal has bencaught,SIGALRM is now blocked*/

??unslept = alarm(0);

?? ???sigaction(SIGALRM,&oldact,NULL);/*resetprevious action*/

??? /*reset signal mask,whichunblocks SIGALRM*/

???sigprocmask(SIG_SETMASK,&oldmask,NULL);

???return(unslept);

}

?

int main(void) {

while(1)

??? {

???? ????sleep(2);

?? printf("Two secondspassed\n");

? ????}

? return 0;

}

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。