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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

进程间通信——信号

發(fā)布時(shí)間:2023/12/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程间通信——信号 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

進(jìn)程間通信——信號(hào)


宗旨:技術(shù)的學(xué)習(xí)是有限的,分享的精神是無限的。


一、信號(hào)和中斷

1、信號(hào)基本概念

(1)發(fā)送信號(hào):產(chǎn)生信號(hào),有多種發(fā)送信號(hào)的方式【一個(gè)進(jìn)程到另一個(gè)進(jìn)程,內(nèi)核向用戶,進(jìn)程向自己】

(2)安裝信號(hào):設(shè)置信號(hào)到來時(shí)不再執(zhí)行默認(rèn)操作,而是執(zhí)行自定義的代碼。

(3)遞送信號(hào):一個(gè)信號(hào)被操作系統(tǒng)發(fā)送到目標(biāo)進(jìn)程引起某段處理程序的執(zhí)行。

(4)捕獲信號(hào):被遞送的信號(hào)在目標(biāo)進(jìn)程引起某段處理程序的執(zhí)行。

(5)屏蔽信號(hào):進(jìn)程告訴操作系統(tǒng)暫時(shí)不接受某些信號(hào)。

(6)忽略信號(hào):進(jìn)程被遞送到目標(biāo)進(jìn)程,但目標(biāo)進(jìn)程不處理,直接丟棄。

(7)未決信號(hào):信號(hào)已經(jīng)產(chǎn)生,但因目標(biāo)進(jìn)程暫時(shí)屏蔽該信號(hào)而不能被目標(biāo)進(jìn)程捕獲到的信號(hào)。

(8)可靠信號(hào)和不可靠信號(hào):編號(hào)小于32的信號(hào)是不可靠信號(hào),大于32的是可靠信號(hào)。

? ? ?信號(hào)的“未決”是一種狀態(tài),指的是從信號(hào)的產(chǎn)生到信號(hào)被處理前的這一段過程。信號(hào)的“屏蔽”是一個(gè)開關(guān)動(dòng)作,指的是暫時(shí)阻止該信號(hào)被處理。

輸入命令kill –l查看系統(tǒng)定義的信號(hào)列表:

$ kill-l

?1) SIGHUP??????2) SIGINT?????? 3) SIGQUIT????? 4) SIGILL?????? 5) SIGTRAP

?6) SIGABRT?????7) SIGEMT?????? 8) SIGFPE?????? 9) SIGKILL???? 10) SIGBUS

11)SIGSEGV???? 12) SIGSYS????? 13) SIGPIPE???? 14) SIGALRM???? 15) SIGTERM

16)SIGURG????? 17) SIGSTOP? ???18)SIGTSTP???? 19) SIGCONT???? 20) SIGCHLD

21)SIGTTIN???? 22) SIGTTOU???? 23) SIGIO?????? 24) SIGXCPU???? 25) SIGXFSZ

26)SIGVTALRM?? 27) SIGPROF???? 28) SIGWINCH??? 29) SIGPWR????? 30) SIGUSR1

31)SIGUSR2???? 32) SIGRTMAX

?

二、發(fā)送信號(hào)

? ? ? ? 發(fā)送信號(hào)是指一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送某個(gè)信號(hào)值,但實(shí)際并不是直接發(fā)送的,而是由OS轉(zhuǎn)發(fā)的。產(chǎn)生一個(gè)信號(hào)有多種情況:

(1) 用戶按下Ctrl-C,這個(gè)鍵盤輸入產(chǎn)生一個(gè)硬件中斷。

(2) 硬件異常產(chǎn)生信號(hào)。對(duì)一個(gè)無效存儲(chǔ)訪問的進(jìn)程產(chǎn)生一個(gè)SIGSEGV

(3) 終止進(jìn)程信號(hào)。其他進(jìn)程調(diào)用kill()函數(shù)可將信號(hào)發(fā)送給另一個(gè)進(jìn)程或進(jìn)程組。

(4) 軟件異常產(chǎn)生信號(hào)。

1、kill發(fā)送一個(gè)信號(hào)到進(jìn)程

? ? ? ? ——傳遞一個(gè)信號(hào)給指定進(jìn)程使用kill()函數(shù),給當(dāng)前進(jìn)程使用raise(),喚醒設(shè)置定時(shí)使用alarm()

(1)函數(shù)原型

#include<signal.h>

intkill(pid_t pid, int sig);

(2)函數(shù)參數(shù)

?????? pid:要被傳遞信號(hào)的進(jìn)程號(hào)(PID)

????????????? pid>0:將信號(hào)發(fā)送給進(jìn)程的PID值為pid的進(jìn)程

????????????? pid=0:將信號(hào)發(fā)送給和當(dāng)前進(jìn)程在同一進(jìn)程組的所有進(jìn)程

????????????? pid=-1:將信號(hào)發(fā)送給系統(tǒng)內(nèi)的所有進(jìn)程

????????????? pid<0:將信號(hào)發(fā)送給進(jìn)程組號(hào)PGID為pid絕對(duì)值的所有信號(hào)

?????? sig:發(fā)送的信號(hào)值

(3)返回值

?????? 成功返回0,失敗返回-1

?????? 可向某個(gè)進(jìn)程發(fā)送kill -0信號(hào)以檢測(cè)進(jìn)程是否存在,因?yàn)楫?dāng)前進(jìn)程總是存在的:

?????? kill(getpid, 0);

?

2、raise自舉一個(gè)信號(hào)

? ? ? ? ——給當(dāng)前進(jìn)程發(fā)送一個(gè)信號(hào),即喚醒一個(gè)進(jìn)程。

(1)函數(shù)原型

?????? #include <signal.h>

?????? int raise(int sig);

(2)函數(shù)參數(shù)

?????? sig:發(fā)送的信號(hào)值

(3)返回值

?????? 成功返回0,失敗返回-1

?????? 此函數(shù)相當(dāng)于:

if(kill(getpid(),sig) == -1)

{

? perror(“raise”);

}

?

3、alarm定時(shí)

? ? ? ? ——傳遞定時(shí)信號(hào),即在多少時(shí)間內(nèi)產(chǎn)生SIGALRM信號(hào),調(diào)用一次產(chǎn)生一個(gè)信號(hào)。

(1)函數(shù)原型

?????? #include <unistd.h>

?????? int alarm(unsigned int seconds);

(2)函數(shù)參數(shù)

?????? seconds:多少時(shí)間內(nèi)發(fā)送SIGALRM信號(hào)給當(dāng)前進(jìn)程

?????? ?????? seconds=0:取消所有發(fā)出的報(bào)警請(qǐng)求

(3)返回值

?????? 在調(diào)用alarm之前沒有調(diào)用過alarm,成功返回0,失敗返回-1;

?????? 此前調(diào)用過alarm函數(shù),則將重新設(shè)置調(diào)用進(jìn)程的鬧鐘,成功,將以當(dāng)前時(shí)間為基準(zhǔn),返回值為上次設(shè)置的alarm將在多少時(shí)間內(nèi)產(chǎn)生SIGALRM信號(hào)。

?

4、ualarm定時(shí)

? ? ? ? ——使當(dāng)前進(jìn)程在指定時(shí)間內(nèi)產(chǎn)生SIGALRM信號(hào),然后每隔指定時(shí)間重復(fù)產(chǎn)生SIGALRM信號(hào)。

(1)函數(shù)原型????

?????? useconds_t ualarm(useconds_t value,useconds_t interval);

(2)函數(shù)參數(shù)

?????? value:指定時(shí)間(us)內(nèi)產(chǎn)生SIGALRM信號(hào)

interval:每隔指定時(shí)間重復(fù)產(chǎn)生SIGALRM

(3)返回值

?????? 成功返回0,

三、安裝信號(hào)和捕捉信號(hào)

1、信號(hào)處理方法

(1) 忽略此信號(hào)。

(2) 執(zhí)行該信號(hào)的默認(rèn)處理動(dòng)作。

(3) 提供一個(gè)信號(hào)處理函數(shù),要求內(nèi)核在處理該信號(hào)時(shí)切換到用戶態(tài)執(zhí)行這個(gè)處理函數(shù),這種方 式稱為捕捉(Catch)一個(gè)信號(hào)。

2、signal安裝信號(hào)

——信號(hào)都有默認(rèn)的處理方式,未做特殊處理,將執(zhí)行默認(rèn)操作;若要做特殊處理,則要安裝信號(hào)處理函數(shù)。

(1)函數(shù)原型

?????? #include <signal.h>

?????? typedef void (*sighandler_t)(int);

?????? sighandler_t signal(int sig, sighandlerhandler);

(2)函數(shù)參數(shù)

?????? sig:接收到的信號(hào)

?????? handler:接收到此信號(hào)后的處理代碼入口

(3)返回值

?????? 成功返回指向針對(duì)此信號(hào)的上一次設(shè)置,執(zhí)行失敗返回SIG_EER(-1)錯(cuò)誤。

3、sigaction安裝信號(hào)

? ? ? ? ——signal只能提供簡(jiǎn)單的信號(hào)安裝操作,并逐步并淘汰。此函數(shù)可用來檢查和更改信號(hào)處理操作。

(1)函數(shù)原型

#include <signal.h> int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);struct sigaction {void (*sa_handler)(int);/* addr of signal handler, *//* or SIG_IGN, or SIG_DFL*/sigset_t sa_mask; /*additional signals to block */int sa_flags; /* signaloptions, Figure 10.16 *//* alternate handler */void (*sa_sigaction)(int, siginfo_t *, void *); };

(2)函數(shù)參數(shù)

?????? signo:指定信號(hào)的編號(hào)

? ? ? ?若act指針非空,則根據(jù)act修改該信號(hào)的處理動(dòng)作。若oact指針非 空,則通過oact傳出該信號(hào)原來的處理動(dòng)作。

(3)返回值

?????? 成功返回0,失敗返回-1。

? ? ? ? 將sa_handler賦值為常數(shù)SIG_IGN傳給sigaction表示忽略信號(hào),賦值為常數(shù)SIG_DFL表示執(zhí)行系統(tǒng)默 認(rèn)動(dòng)作,賦值為一個(gè)函數(shù)指針表示用自定義函數(shù)捕捉信號(hào),或者說向內(nèi)核注冊(cè)了一個(gè)信號(hào)處理函 數(shù),該函數(shù)返回值為void,可以帶一個(gè)int參數(shù),通過參數(shù)可以得知當(dāng)前信號(hào)的編號(hào),這樣就可以 用同一個(gè)函數(shù)處理多種信號(hào)。顯然,這也是一個(gè)回調(diào)函數(shù),不是被main函數(shù)調(diào)用,而是被系統(tǒng)所調(diào)用。

? ? ? ? 當(dāng)某個(gè)信號(hào)的處理函數(shù)被調(diào)用時(shí),內(nèi)核自動(dòng)將當(dāng)前信號(hào)加入進(jìn)程的信號(hào)屏蔽字,當(dāng)信號(hào)處理函數(shù)返 回時(shí)自動(dòng)恢復(fù)原來的信號(hào)屏蔽字,這樣就保證了在處理某個(gè)信號(hào)時(shí),如果這種信號(hào)再次產(chǎn)生,那么它會(huì)被阻塞到當(dāng)前處理結(jié)束為止。如果在調(diào)用信號(hào)處理函數(shù)時(shí),除了當(dāng)前信號(hào)被自動(dòng)屏蔽之外,還希望自動(dòng)屏蔽另外一些信號(hào),則用sa_mask字段說明這些需要額外屏蔽的信號(hào),當(dāng)信號(hào)處理函數(shù)返 回時(shí)自動(dòng)恢復(fù)原來的信號(hào)屏蔽字。 sa_flags字段包含一些選項(xiàng),我把sa_flags設(shè)為0, sa_sigaction是實(shí)時(shí)信號(hào)的處理函數(shù)。?

四、信號(hào)集操作

信號(hào)忽略:系統(tǒng)仍然傳遞該信號(hào),指示相應(yīng)進(jìn)程對(duì)該信號(hào)不做任何處理。

信號(hào)屏蔽:即使傳遞信號(hào)給該進(jìn)程,該進(jìn)程也不捕捉信號(hào)。

#define SIGSET_NWOEDS (1024 / (8 * sizeof(unsigned long int)))typedef struct {unsigned long int val[SIGSET_NWOEDS]; } sigset_t;

1、sigprocmask

? ? ? ? ?——設(shè)置進(jìn)程屏蔽信號(hào)集

(1)函數(shù)原型

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

(2)函數(shù)參數(shù)

如果oset是非空指針,則讀取進(jìn)程的當(dāng)前信號(hào)屏蔽字通過oset參數(shù)傳出。如果set是非空指針,則更改進(jìn)程的信號(hào)屏蔽字,參數(shù)how指示如何更改。如果oset和set都是非空指針,則先將原來的信號(hào) 屏蔽字備份到oset里,然后根據(jù)set和how參數(shù)更改信號(hào)屏蔽字。假設(shè)當(dāng)前的信號(hào)屏蔽字為mask,下表說明了how參數(shù)的可選值。

SIG_BLOCK

set包含了我們希望添加到當(dāng)前信號(hào)屏蔽字的信號(hào),相當(dāng) 于mask=mask|set

SIG_UNBLOCK

set包含了我們希望從當(dāng)前信號(hào)屏蔽字中解除阻塞的信號(hào),相當(dāng) 于mask=mask&~set

SIG_SETMASK

設(shè)置當(dāng)前信號(hào)屏蔽字為set所指向的值,相當(dāng)于mask=set

?

(3)返回值

?????? 若成功則為0,若出錯(cuò)則為-1

?

2、sigpending

#include <signal.h>
int sigpending(sigset_t *set);

? ? ? ? ——讀取當(dāng)前進(jìn)程的未決信號(hào)集,通過set參數(shù)傳出。調(diào)用成功則返回0,出錯(cuò)則返回-1。

#include<signal.h> #include<stdio.h> #include<unistd.h>void printsigset(const sigset_t *set) {int i;for (i = 1; i < 32; i++)if (sigismember(set, i) == 1){putchar('1');}else{putchar('0');}puts(""); }int main(void) {sigset_t s, p;sigemptyset(&s);sigaddset(&s, SIGINT);sigprocmask(SIG_BLOCK, &s, NULL);while (1){sigpending(&p);printsigset(&p);sleep(1);}return 0; }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

3、信號(hào)集

#include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set, int signo); int sigismember(const sigset_t *set, int signo);

? ? ? ? 函數(shù)sigemptyset初始化set所指向的信號(hào)集,使其中所有信號(hào)的對(duì)應(yīng)bit清零,表示該信號(hào)集不包含任何有效信號(hào)。函數(shù)sigfillset初始化set所指向的信號(hào)集,使其中所有信號(hào)的對(duì)應(yīng)bit置位,表示 該信號(hào)集的有效信號(hào)包括系統(tǒng)支持的所有信號(hào)。注意,在使用sigset_t類型的變量之前,一定要調(diào)用sigemptyset或sigfillset做初始化,使信號(hào)集處于確定的狀態(tài)。初始化sigset_t變量之后就可以在調(diào)用sigaddset和sigdelset在該信號(hào)集中添加或刪除某種有效信號(hào)。這四個(gè)函數(shù)都是成功返 回0,出錯(cuò)返回-1。 sigismember是一個(gè)布爾函數(shù),用于判斷一個(gè)信號(hào)集的有效信號(hào)中是否包含某種信號(hào),若包含則返回1,不包含則返回0,出錯(cuò)返回-1。

?

五、等待信號(hào)

? ? ? ? 進(jìn)程可以因等待某些特定的信號(hào)而阻塞,pause()函數(shù)用來等待除當(dāng)前進(jìn)程外的任意信號(hào),而sigsuspend()用來等待指定信號(hào)以外的任意信號(hào)。

1pause

? ? ? ? ——使調(diào)用進(jìn)程掛起直到有信號(hào)遞達(dá)

(1)函數(shù)原型

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

(2)參數(shù)返回值

?????? 如果信號(hào)的處理動(dòng)作是終止進(jìn)程,則進(jìn)程終止, pause函數(shù)沒有機(jī)會(huì)返回;如果信號(hào)的處理動(dòng)作是忽略,則進(jìn)程繼續(xù)處于掛起狀態(tài), pause不返回;如果信號(hào)的處理動(dòng)作是捕捉,則調(diào)用了信號(hào)處理函數(shù)之后pause返回-1, errno設(shè)置為EINTR, 所以pause只有出錯(cuò)的返回值。

// 用alarm和pause實(shí)現(xiàn)sleep(3)函數(shù) #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);pause();unslept = alarm(0);sigaction(SIGALRM, &oldact, NULL);return unslept; } int main(void) {while(1){mysleep(2);printf("Two secondspassed\n");}return 0; }

(1) main函數(shù)調(diào)用mysleep函數(shù),后者調(diào)用sigaction注冊(cè)了SIGALRM信號(hào)的處理函數(shù)sig_alrm。

(2) 調(diào)用alarm(nsecs)設(shè)定鬧鐘。

(3) 調(diào)用pause等待,內(nèi)核切換到別的進(jìn)程運(yùn)行。

(4) nsecs秒之后,鬧鐘超時(shí),內(nèi)核發(fā)SIGALRM給這個(gè)進(jìn)程。

(5) 從內(nèi)核態(tài)返回這個(gè)進(jìn)程的用戶態(tài)之前處理未決信號(hào),發(fā)現(xiàn)有SIGALRM信號(hào),其處理函數(shù) 是sig_alrm。

(6) 切換到用戶態(tài)執(zhí)行sig_alrm函數(shù),進(jìn)入sig_alrm函數(shù)時(shí)SIGALRM信號(hào)被自動(dòng)屏蔽,從sig_alrm函數(shù)返回時(shí)SIGALRM信號(hào)自動(dòng)解除屏蔽。然后自動(dòng)執(zhí)行系統(tǒng)調(diào)用sigreturn再次進(jìn)入 內(nèi)核,再返回用戶態(tài)繼續(xù)執(zhí)行進(jìn)程的主控制流程( main函數(shù)調(diào)用的mysleep函數(shù))。

(7)pause函數(shù)返回-1,然后調(diào)用alarm(0)取消鬧鐘,調(diào)用sigaction恢復(fù)SIGALRM信號(hào)以前的處理。

?

可重入函數(shù)——如果一個(gè)函數(shù)符合以下條件之一則是不可重入的:

調(diào)用了malloc或free,因?yàn)閙alloc也是用全局鏈表來管理堆的。

調(diào)用了標(biāo)準(zhǔn)I/O庫(kù)函數(shù)。標(biāo)準(zhǔn)I/O庫(kù)的很多實(shí)現(xiàn)都以不可重入的方式使用全局?jǐn)?shù)據(jù)結(jié)構(gòu)。

【通俗說:使用了全局變量的都是不可重入的】? ? ? ?

總結(jié)

以上是生活随笔為你收集整理的进程间通信——信号的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。