色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 學習筆記 > 嵌入式學習筆記:linux進程通信之信號函數(shù)

嵌入式學習筆記:linux進程通信之信號函數(shù) 時間:2018-09-26      來源:未知

1、信號注冊函數(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 哪個信號

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

方式處理

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

2、修改信號處理動作(通常在Linux用其來注冊一個信號的捕捉函數(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:該元素是過時的,不應(yīng)該使用,POSIX.1標準將不指定該元素。(棄用)

sa_sigaction:當sa_flags被指定為SA_SIGINFO標志時,使用該信號處理程序。(很少使用)

重點掌握:

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

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

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

內(nèi)核實現(xiàn)信號捕捉過程:

信號捕捉特性:

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

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

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

隊)

3、pause函數(shù) : 掛起當前的進程,直到收到一個信號,才會接著執(zhí)行

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

int pause(void);

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

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

值。

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

4、alarm函數(shù)

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

每個進程都有且只有唯一個定時器。

unsigned int alarm(unsigned int seconds);

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

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

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

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

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

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

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

int raise(int sig);

成功:0,失敗非0值

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

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

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

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

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

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

成功:0;失敗:-1 (ID非法,信號非法,普通用戶殺init進程等權(quán)級問題),設(shè)置errno sig:不推薦直接使用數(shù)字,應(yīng)使用宏名,因為不同操作系統(tǒng)信號編號可能不同,但名稱一致。

pid > 0: 發(fā)送信號給指定的進程。

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

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

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

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

相同。

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

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

 

時序競態(tài)

設(shè)想如下場景:

欲睡覺,定鬧鐘10分鐘,希望10分鐘后鬧鈴將自己喚醒。

正常:定時,睡覺,10分鐘后被鬧鐘喚醒。

異常:鬧鐘定好后,被喚走,外出勞動,20分鐘后勞動結(jié)束。回來繼續(xù)睡覺計劃,但勞動期間鬧鐘已經(jīng)響過,不會再將我喚醒。

時序問題分析

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

1. 注冊SIGALRM信號處理函數(shù) (sigaction...)

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

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

4. 1秒后,鬧鐘超時,內(nèi)核向當前進程發(fā)送SIGALRM信號(自然定時法,與進程狀態(tài)無

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

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

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

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

等待alarm函數(shù)發(fā)送的SIGALRM信號將自己喚醒)

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

解決時序問題

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

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

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

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

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

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

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

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

8、setitimer函數(shù)

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

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

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

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

① 自然定時:ITIMER_REAL → 14)SIGLARM 計算自然時間

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

用cpu的時間

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

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

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

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

信號集設(shè)定:

sigset_t set; // typedef unsigned long sigset_t;

int sigemptyset(sigset_t *set); //將某個信號集清0

成功:0;失敗:-1

int sigfillset(sigset_t *set); //將某個信號集置

1

成功:0;失敗:-1

int sigaddset(sigset_t *set, int signum); //將某個信號加入信號集

成功:0;失敗:-1

int sigdelset(sigset_t *set, int signum); //將某個信號清出信號集

成功:0;失敗:-1

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

集中

返回值:在集合:1;不在:0;出錯:-1

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

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

對比認知select 函數(shù)。

9、sigprocmask函數(shù)

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

中)

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

丟處理。

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

參數(shù):

set:傳入?yún)?shù),是一個位圖,set中哪位置1,就表示當前進程屏蔽哪個信號。

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

how參數(shù)取值:假設(shè)當前的信號屏蔽字為mask

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

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

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

前,至少將其中一個信號遞達。

10、sigpending函數(shù)

讀取當前進程的未決信號集

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

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

上一篇:嵌入式學習筆記:linux進程間通信-消息隊列、信號集

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

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

回到頂部

主站蜘蛛池模板: 东京热无码一区二区三区av | 少妇被多人C夜夜爽爽AV | 2020无码专区人妻系列日韩 | 手机看片麻豆 | 天天做天天爱天天爽综合网 | 久久深夜 | 亚洲精品a区 | RUNAWAY在线观看韩国动漫 | 亚洲国产精品成人精品无码区在线 | 国产福利视频一区 | 99视频精品全部在线观看 | 让少妇高潮无乱码高清在线观看 | 在线中文字幕有码中文 | 日产学生妹在线观看 | 18以下看的禁片免费 | 农村欧美丰满熟妇xxxx | 国产AV巨作情欲放纵无码 | 欧美xxxxx在线观看 | 免费无码又爽又高潮视频 | 特级淫片日本高清视频免费 | 三年片中国在线观看免费大全 | 中文字幕一区二区三区门四区五区 | 久久九九有精品国产 | 久久久久免费看黄A片 | www.av天堂com| 高清日韩av在线影院 | 日本人妻中文字幕乱码系列 | 日本一二三区在线观看 | 中国一级黄色片 | 久久免费看少妇高潮a片特黄 | 久久99热这里只有精品8 | 日本一上一下爱爱免费 | 亚洲AV永久无码一区二区三区 | 国产女人乱子对白AV片 | 性XXXXFREEXXXXX牲交 | 亚洲国产人在线播放首页 | 国产精品无码一区二区牛牛 | 公妇仑乱在线观看 | 熟女俱乐部五十路六十路av | 四虎影院永久免费观看 | 狠狠cao日日橹夜夜十橹 |