久久精品国产清自在天天线_日韩国产欧美系列_亚洲天堂影视在线观看_91在线艹亚洲无码午夜_日本写真高清视频免费网站网_亚州无码大尺度另类_高跟翘臀老师后进式视频午夜_久久精品国产亚洲AV热黑人_国产另ts另类人妖_丁香五月 开心五月 激情五月

當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 學(xué)習(xí)筆記 > 嵌入式學(xué)習(xí)筆記:linux進(jìn)程通信之信號(hào)函數(shù)

嵌入式學(xué)習(xí)筆記:linux進(jìn)程通信之信號(hào)函數(shù) 時(shí)間:2018-09-26      來(lái)源:未知

1、信號(hào)注冊(cè)函數(shù): signal

#include

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

sighandler_t signal(int signum, sighandler_t handler);

入?yún)ⅲ?/p>

signum 哪個(gè)信號(hào)

handle 信號(hào)所對(duì)應(yīng)的處理函數(shù);SIG_IGN:忽略此信號(hào);SIG_DFL:按系統(tǒng)默認(rèn)

方式處理

該函數(shù)由ANSI定義,由于歷史原因在不同版本的Unix和不同版本的Linux中可能有不同的行為。因此應(yīng)該盡量避免使用它,取而代之使用sigaction函數(shù)。

2、修改信號(hào)處理動(dòng)作(通常在Linux用其來(lái)注冊(cè)一個(gè)信號(hào)的捕捉函數(shù))

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

成功:0;失�。�-1,設(shè)置errno

參數(shù):

act:傳入?yún)?shù),新的處理方式。

oldact:傳出參數(shù),舊的處理方式。

struct sigaction結(jié)構(gòu)體

struct sigaction {

void

void

sigset_t

int

void

(*sa_handler)(int);

(*sa_sigaction)(int, siginfo_t *, void *);

sa_mask;

sa_flags;

(*sa_restorer)(void);

};

sa_restorer:該元素是過(guò)時(shí)的,不應(yīng)該使用,POSIX.1標(biāo)準(zhǔn)將不指定該元素。(棄用)

sa_sigaction:當(dāng)sa_flags被指定為SA_SIGINFO標(biāo)志時(shí),使用該信號(hào)處理程序。(很少使用)

重點(diǎn)掌握:

① sa_handler:指定信號(hào)捕捉后的處理函數(shù)名(即注冊(cè)函數(shù))。也可賦值為SIG_IGN表忽略 或 SIG_DFL表執(zhí)行默認(rèn)動(dòng)作

② sa_mask: 調(diào)用信號(hào)處理函數(shù)時(shí),所要屏蔽的信號(hào)集合(信號(hào)屏蔽字)。注意:僅在處理函數(shù)被調(diào)用期間屏蔽生效,是臨時(shí)性設(shè)置。

③ sa_flags:通常設(shè)置為0,表使用默認(rèn)屬性。

內(nèi)核實(shí)現(xiàn)信號(hào)捕捉過(guò)程:

信號(hào)捕捉特性:

1、進(jìn)程正常運(yùn)行時(shí),默認(rèn)PCB中有一個(gè)信號(hào)屏蔽字,假定為☆,它決定了進(jìn)程自動(dòng)屏蔽哪些信號(hào)。當(dāng)注冊(cè)了某個(gè)信號(hào)捕捉函數(shù),捕捉到該信號(hào)以后,要調(diào)用該函數(shù)。而該函數(shù)有可能執(zhí)行很長(zhǎng)時(shí)間,在這期間所屏蔽的信號(hào)不由☆來(lái)指定。而是用sa_mask來(lái)指定。調(diào)用完信號(hào)處理函數(shù),再恢復(fù)為☆。

2、XXX信號(hào)捕捉函數(shù)執(zhí)行期間,XXX信號(hào)自動(dòng)被屏蔽。

3、阻塞的常規(guī)信號(hào)不支持排隊(duì),產(chǎn)生多次只記錄一次。(后32個(gè)實(shí)時(shí)信號(hào)支持排

隊(duì))

3、pause函數(shù) : 掛起當(dāng)前的進(jìn)程,直到收到一個(gè)信號(hào),才會(huì)接著執(zhí)行

調(diào)用該函數(shù)可以造成進(jìn)程主動(dòng)掛起,等待信號(hào)喚醒。調(diào)用該系統(tǒng)調(diào)用的進(jìn)程將處于阻塞狀態(tài)(主動(dòng)放棄cpu) 直到有信號(hào)遞達(dá)將其喚醒。

int pause(void);

返回值:-1 并設(shè)置errno為EINTR

① 如果信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,則進(jìn)程終止,pause函數(shù)么有機(jī)會(huì)返回。 ② 如果信號(hào)的默認(rèn)處理動(dòng)作是忽略,進(jìn)程繼續(xù)處于掛起狀態(tài),pause函數(shù)不返回。 ③ 如果信號(hào)的處理動(dòng)作是捕捉,則【調(diào)用完信號(hào)處理函數(shù)之后,pause返回-1】errno設(shè)置為 EINTR,表示“被信號(hào)中斷”。想想我們還有哪個(gè)函數(shù)只有出錯(cuò)返回

值。

④ pause收到的信號(hào)不能被屏蔽,如果被屏蔽,那么pause就不能被喚醒。

4、alarm函數(shù)

設(shè)置定時(shí)器(鬧鐘)。在指定seconds后,內(nèi)核會(huì)給當(dāng)前進(jìn)程發(fā)送14)SIGALRM信號(hào)。進(jìn)程收到該信號(hào),默認(rèn)動(dòng)作終止。

每個(gè)進(jìn)程都有且只有唯一個(gè)定時(shí)器。

unsigned int alarm(unsigned int seconds);

返回0或剩余的秒數(shù),無(wú)失敗。

常用:取消定時(shí)器alarm(0),返回舊鬧鐘余下秒數(shù)。

例:alarm(5) → 3sec → alarm(4) → 5sec → alarm(5) → alarm(0)

定時(shí),與進(jìn)程狀態(tài)無(wú)關(guān)(自然定時(shí)法)!就緒、運(yùn)行、掛起(阻塞、暫停)、終止、僵尸...無(wú)論進(jìn)程處于何種狀態(tài),alarm都計(jì)時(shí)。

使用time命令查看程序執(zhí)行的時(shí)間。程序運(yùn)行的瓶頸在于IO,優(yōu)化程序,首選優(yōu)化IO。

實(shí)際執(zhí)行時(shí)間 = 系統(tǒng)時(shí)間 + 用戶時(shí)間 + 等待時(shí)間

5、raise函數(shù): 自己給自己發(fā)送信號(hào) raise(signo) == kill(getpid(), signo);

int raise(int sig);

成功:0,失敗非0值

入?yún)ⅲ?發(fā)送的信號(hào)

6、abort 函數(shù):給自己發(fā)送異常終止信號(hào) 6) SIGABRT 信號(hào),終止并產(chǎn)生core文件 void abort(void); //該函數(shù)無(wú)返回

kill函數(shù)/命令產(chǎn)生信號(hào)

1、kill命令產(chǎn)生信號(hào):kill -SIGKILL pid

2、kill函數(shù):給指定進(jìn)程發(fā)送指定信號(hào)(不一定殺死)

7、int kill(pid_t pid, int sig);

成功:0;失�。�-1 (ID非法,信號(hào)非法,普通用戶殺init進(jìn)程等權(quán)級(jí)問(wèn)題),設(shè)置errno sig:不推薦直接使用數(shù)字,應(yīng)使用宏名,因?yàn)椴煌僮飨到y(tǒng)信號(hào)編號(hào)可能不同,但名稱一致。

pid > 0: 發(fā)送信號(hào)給指定的進(jìn)程。

pid = = 0: 發(fā)送信號(hào)給 與調(diào)用kill函數(shù)進(jìn)程屬于同一進(jìn)程組的所有進(jìn)程。

pid < 0: 取|pid|發(fā)給對(duì)應(yīng)進(jìn)程組。

pid = = -1:發(fā)送給進(jìn)程有權(quán)限發(fā)送的系統(tǒng)中所有進(jìn)程。

進(jìn)程組:每個(gè)進(jìn)程都屬于一個(gè)進(jìn)程組,進(jìn)程組是一個(gè)或多個(gè)進(jìn)程集合,他們相互關(guān)聯(lián),共同完成一個(gè)實(shí)體任務(wù),每個(gè)進(jìn)程組都有一個(gè)進(jìn)程組長(zhǎng),默認(rèn)進(jìn)程組ID與進(jìn)程組長(zhǎng)ID

相同。

權(quán)限保護(hù):super用戶(root)可以發(fā)送信號(hào)給任意用戶,普通用戶是不能向系統(tǒng)用戶發(fā)送信號(hào)的。 kill -9 (root用戶的pid) 是不可以的。同樣,普通用戶也不能向其他

普通用戶發(fā)送信號(hào),終止其進(jìn)程。 只能向自己創(chuàng)建的進(jìn)程發(fā)送信號(hào)。普通用戶基本規(guī)則是:發(fā)送者實(shí)際或有效用戶ID == 接收者實(shí)際或有效用戶ID

 

時(shí)序競(jìng)態(tài)

設(shè)想如下場(chǎng)景:

欲睡覺(jué),定鬧鐘10分鐘,希望10分鐘后鬧鈴將自己?jiǎn)拘选?/p>

正常:定時(shí),睡覺(jué),10分鐘后被鬧鐘喚醒。

異常:鬧鐘定好后,被喚走,外出勞動(dòng),20分鐘后勞動(dòng)結(jié)束�;貋�(lái)繼續(xù)睡覺(jué)計(jì)劃,但勞動(dòng)期間鬧鐘已經(jīng)響過(guò),不會(huì)再將我喚醒。

時(shí)序問(wèn)題分析

回顧,借助pause和alarm實(shí)現(xiàn)的mysleep函數(shù)。設(shè)想如下時(shí)序:

1. 注冊(cè)SIGALRM信號(hào)處理函數(shù) (sigaction...)

2. 調(diào)用alarm(1) 函數(shù)設(shè)定鬧鐘1秒。

3. 函數(shù)調(diào)用剛結(jié)束,開(kāi)始倒計(jì)時(shí)1秒。當(dāng)前進(jìn)程失去cpu,內(nèi)核調(diào)度優(yōu)先級(jí)高的進(jìn)程(有多個(gè))取代當(dāng)前進(jìn)程。當(dāng)前進(jìn)程無(wú)法獲得cpu,進(jìn)入就緒態(tài)等待cpu。

4. 1秒后,鬧鐘超時(shí),內(nèi)核向當(dāng)前進(jìn)程發(fā)送SIGALRM信號(hào)(自然定時(shí)法,與進(jìn)程狀態(tài)無(wú)

關(guān)),高優(yōu)先級(jí)進(jìn)程尚未執(zhí)行完,當(dāng)前進(jìn)程仍處于就緒態(tài),信號(hào)無(wú)法處理(未決)

5. 優(yōu)先級(jí)高的進(jìn)程執(zhí)行完,當(dāng)前進(jìn)程獲得cpu資源,內(nèi)核調(diào)度回當(dāng)前進(jìn)程執(zhí)行。

SIGALRM信號(hào)遞達(dá),信號(hào)設(shè)置捕捉,執(zhí)行處理函數(shù)sig_alarm。

6. 信號(hào)處理函數(shù)執(zhí)行結(jié)束,返回當(dāng)前進(jìn)程主控流程,pause()被調(diào)用掛起等待。(欲

等待alarm函數(shù)發(fā)送的SIGALRM信號(hào)將自己?jiǎn)拘?

7. SIGALRM信號(hào)已經(jīng)處理完畢,pause不會(huì)等到。

解決時(shí)序問(wèn)題

可以通過(guò)設(shè)置屏蔽SIGALRM的方法來(lái)控制程序執(zhí)行邏輯,但無(wú)論如何設(shè)置,程序都有可能在“解除信號(hào)屏蔽”與“掛起等待信號(hào)”這個(gè)兩個(gè)操作間隙失去cpu資源。除非將這兩步驟合并成一個(gè)“原子操作”。sigsuspend函數(shù)具備這個(gè)功能。在對(duì)時(shí)序要求嚴(yán)格的場(chǎng)

合下都應(yīng)該使用sigsuspend替換pause。

int sigsuspend(const sigset_t *mask);//掛起等待信號(hào)。

sigsuspend函數(shù)調(diào)用期間,進(jìn)程信號(hào)屏蔽字由其參數(shù)mask指定。

可將某個(gè)信號(hào)(如SIGALRM)從臨時(shí)信號(hào)屏蔽字mask中刪除,這樣在調(diào)用sigsuspend時(shí)將解除對(duì)該信號(hào)的屏蔽,然后掛起等待,當(dāng)sigsuspend返回時(shí),進(jìn)程的信號(hào)屏蔽字恢復(fù)為原來(lái)的值。如果原來(lái)對(duì)該信號(hào)是屏蔽態(tài),sigsuspend函數(shù)返回后仍然屏蔽該信號(hào)。

競(jìng)態(tài)條件,跟系統(tǒng)負(fù)載有很緊密的關(guān)系,體現(xiàn)出信號(hào)的不可靠性。系統(tǒng)負(fù)載越嚴(yán)重,信號(hào)不可靠性越強(qiáng)。

不可靠由其實(shí)現(xiàn)原理所致。信號(hào)是通過(guò)軟件方式實(shí)現(xiàn)(跟內(nèi)核調(diào)度高度依賴,延時(shí)性強(qiáng)),每次系統(tǒng)調(diào)用結(jié)束后,或中斷處理處理結(jié)束后,需通過(guò)掃描PCB中的未決信號(hào)集,來(lái)判斷是否應(yīng)處理某個(gè)信號(hào)。當(dāng)系統(tǒng)負(fù)載過(guò)重時(shí),會(huì)出現(xiàn)時(shí)序混亂。

這種意外情況只能在編寫(xiě)程序過(guò)程中,提早預(yù)見(jiàn),主動(dòng)規(guī)避,而無(wú)法通過(guò)gdb程序調(diào)試等其他手段彌補(bǔ)。且由于該錯(cuò)誤不具規(guī)律性,后期捕捉和重現(xiàn)十分困難。

8、setitimer函數(shù)

設(shè)置定時(shí)器(鬧鐘)。 可代替alarm函數(shù)。精度微秒us,可以實(shí)現(xiàn)周期定時(shí)。

int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

成功:0;失�。�-1,設(shè)置errno

參數(shù):which:指定定時(shí)方式

① 自然定時(shí):ITIMER_REAL → 14)SIGLARM 計(jì)算自然時(shí)間

② 虛擬空間計(jì)時(shí)(用戶空間):ITIMER_VIRTUAL → 26)SIGVTALRM 只計(jì)算進(jìn)程占

用cpu的時(shí)間

③ 運(yùn)行時(shí)計(jì)時(shí)(用戶+內(nèi)核):ITIMER_PROF → 27)SIGPROF 計(jì)算占用cpu及執(zhí)行系

統(tǒng)調(diào)用的時(shí)間

信號(hào)集操作函數(shù):

內(nèi)核通過(guò)讀取未決信號(hào)集來(lái)判斷信號(hào)是否應(yīng)被處理。信號(hào)屏蔽字mask可以影響未決信號(hào)集。而我們可以在應(yīng)用程序中自定義set來(lái)改變mask。已達(dá)到屏蔽指定信號(hào)的目的。

信號(hào)集設(shè)定:

sigset_t set; // typedef unsigned long sigset_t;

int sigemptyset(sigset_t *set); //將某個(gè)信號(hào)集清0

成功:0;失敗:-1

int sigfillset(sigset_t *set); //將某個(gè)信號(hào)集置

1

成功:0;失�。�-1

int sigaddset(sigset_t *set, int signum); //將某個(gè)信號(hào)加入信號(hào)集

成功:0;失敗:-1

int sigdelset(sigset_t *set, int signum); //將某個(gè)信號(hào)清出信號(hào)集

成功:0;失�。�-1

int sigismember(const sigset_t *set, int signum);//判斷某個(gè)信號(hào)是否在信號(hào)

集中

返回值:在集合:1;不在:0;出錯(cuò):-1

sigset_t類型的本質(zhì)是位圖。但不應(yīng)該直接使用位操作,而應(yīng)該使用上述函數(shù),保證

跨系統(tǒng)操作有效。

對(duì)比認(rèn)知select 函數(shù)。

9、sigprocmask函數(shù)

用來(lái)屏蔽信號(hào)、解除屏蔽也使用該函數(shù)。其本質(zhì),讀取或修改進(jìn)程的信號(hào)屏蔽字(PCB

中)

嚴(yán)格注意,屏蔽信號(hào):只是將信號(hào)處理延后執(zhí)行(延至解除屏蔽);而忽略表示將信號(hào)

丟處理。

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); 成功:0;失敗:-1,設(shè)置errno

參數(shù):

set:傳入?yún)?shù),是一個(gè)位圖,set中哪位置1,就表示當(dāng)前進(jìn)程屏蔽哪個(gè)信號(hào)。

oldset:傳出參數(shù),保存舊的信號(hào)屏蔽集。

how參數(shù)取值:假設(shè)當(dāng)前的信號(hào)屏蔽字為mask

SIG_BLOCK: 當(dāng)how設(shè)置為此值,set表示需要屏蔽的信號(hào)。相當(dāng)于 mask = mask|set

SIG_UNBLOCK: 當(dāng)how設(shè)置為此,set表示需要解除屏蔽的信號(hào)。相當(dāng)于 mask = mask & ~set

SIG_SETMASK: 當(dāng)how設(shè)置為此,set表示用于替代原始屏蔽及的新屏蔽集。相當(dāng)于 mask = set若,調(diào)用sigprocmask解除了對(duì)當(dāng)前若干個(gè)信號(hào)的阻塞,則在sigprocmask返回

前,至少將其中一個(gè)信號(hào)遞達(dá)。

10、sigpending函數(shù)

讀取當(dāng)前進(jìn)程的未決信號(hào)集

int sigpending(sigset_t *set); //set傳出參數(shù)。

返回值:成功:0;失�。�-1,設(shè)置errno

上一篇:嵌入式學(xué)習(xí)筆記:linux進(jìn)程間通信-消息隊(duì)列、信號(hào)集

下一篇:嵌入式學(xué)習(xí)筆記:指針函數(shù)詳解

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺(tái)專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見(jiàn)科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號(hào)-5,京公海網(wǎng)安備11010802025203號(hào)

回到頂部