久久婷婷香蕉热狠狠综合,精品无码国产自产拍在线观看蜜,寡妇房东在做爰3,中文字幕日本人妻久久久免费,国产成人精品三上悠亚久久

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

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

1、信號注冊函數: signal

#include

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

sighandler_t signal(int signum, sighandler_t handler);

入參:

signum 哪個(ge)信號

handle 信號(hao)所對(dui)應的處(chu)理函數;SIG_IGN:忽略此信號(hao);SIG_DFL:按系(xi)統(tong)默認(ren)

方式處理

該(gai)函(han)數由ANSI定義,由于(yu)歷史原(yuan)因在不同版(ban)本的(de)Unix和(he)不同版(ban)本的(de)Linux中可能有不同的(de)行為。因此應該(gai)盡量避免使用它(ta),取(qu)而(er)代(dai)之使用sigaction函(han)數。

2、修改信(xin)號處理動作(通常在(zai)Linux用其來(lai)注冊一(yi)個信(xin)號的捕捉函數)

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

成功:0;失敗:-1,設置errno

參數:

act:傳入參數,新的處理方式。

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

struct sigaction結構體

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:該元(yuan)素是(shi)過時的,不(bu)應該使用,POSIX.1標準將不(bu)指(zhi)定該元(yuan)素。(棄(qi)用)

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

重點掌握:

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

② sa_mask: 調用信號處理函(han)數(shu)時(shi),所要屏蔽的信號集合(信號屏蔽字)。注意(yi):僅在處理函(han)數(shu)被調用期間屏蔽生效(xiao),是臨時(shi)性設置。

③ sa_flags:通常(chang)設(she)置為0,表(biao)使(shi)用默認(ren)屬性。

內核實現信號捕捉過(guo)程:

信號捕捉特(te)性:

1、進程(cheng)正(zheng)常運行時,默認PCB中(zhong)有一個(ge)信(xin)(xin)號(hao)(hao)(hao)屏蔽字(zi),假定為☆,它(ta)決(jue)定了進程(cheng)自動屏蔽哪些信(xin)(xin)號(hao)(hao)(hao)。當注冊了某個(ge)信(xin)(xin)號(hao)(hao)(hao)捕捉函數,捕捉到該(gai)信(xin)(xin)號(hao)(hao)(hao)以后(hou),要調用該(gai)函數。而(er)該(gai)函數有可能執(zhi)行很長時間,在這期間所屏蔽的信(xin)(xin)號(hao)(hao)(hao)不由☆來指定。而(er)是用sa_mask來指定。調用完信(xin)(xin)號(hao)(hao)(hao)處理函數,再恢復為☆。

2、XXX信號捕捉(zhuo)函數(shu)執行期間,XXX信號自(zi)動被屏蔽。

3、阻塞(sai)的常(chang)規信號不支(zhi)持(chi)排隊,產生多次只記錄一(yi)次。(后32個實時(shi)信號支(zhi)持(chi)排

隊)

3、pause函(han)數(shu) : 掛起當前的進(jin)程,直到(dao)收到(dao)一個(ge)信號(hao),才會接(jie)著執行

調(diao)(diao)用該函數可以造成(cheng)進程(cheng)主動掛起,等待(dai)信號(hao)喚(huan)(huan)醒。調(diao)(diao)用該系統調(diao)(diao)用的進程(cheng)將處于阻塞狀態(主動放棄cpu) 直(zhi)到有(you)信號(hao)遞達將其喚(huan)(huan)醒。

int pause(void);

返(fan)回值:-1 并設置errno為(wei)EINTR

① 如(ru)(ru)(ru)果信(xin)(xin)號的(de)默認處(chu)理動(dong)(dong)作是(shi)終止進程,則進程終止,pause函(han)數么有機會返回(hui)。 ② 如(ru)(ru)(ru)果信(xin)(xin)號的(de)默認處(chu)理動(dong)(dong)作是(shi)忽(hu)略,進程繼續處(chu)于掛起狀態,pause函(han)數不返回(hui)。 ③ 如(ru)(ru)(ru)果信(xin)(xin)號的(de)處(chu)理動(dong)(dong)作是(shi)捕捉,則【調用完信(xin)(xin)號處(chu)理函(han)數之后,pause返回(hui)-1】errno設置為 EINTR,表示“被信(xin)(xin)號中斷”。想(xiang)想(xiang)我們還有哪個函(han)數只有出(chu)錯返回(hui)

值。

④ pause收到的信號不能(neng)被屏(ping)蔽,如果被屏(ping)蔽,那么pause就(jiu)不能(neng)被喚醒(xing)。

4、alarm函(han)數(shu)

設置定(ding)時器(鬧鐘)。在指定(ding)seconds后,內核會給當前進程(cheng)(cheng)發(fa)送14)SIGALRM信號。進程(cheng)(cheng)收到該信號,默認(ren)動(dong)作終止。

每個進程都有且只有唯一(yi)個定(ding)時器。

unsigned int alarm(unsigned int seconds);

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

常用:取消定時器alarm(0),返回(hui)舊鬧鐘(zhong)余下(xia)秒(miao)數(shu)。

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

定(ding)時(shi)(shi),與進程狀(zhuang)態(tai)無關(自然定(ding)時(shi)(shi)法)!就緒、運(yun)行(xing)、掛起(qi)(阻塞、暫停)、終(zhong)止、僵尸...無論進程處于何種狀(zhuang)態(tai),alarm都計時(shi)(shi)。

使用(yong)time命令查(cha)看(kan)程(cheng)序(xu)執(zhi)行(xing)(xing)的時(shi)間。程(cheng)序(xu)運行(xing)(xing)的瓶頸在(zai)于(yu)IO,優化程(cheng)序(xu),首選優化IO。

實際(ji)執行時(shi)間 = 系統時(shi)間 + 用戶時(shi)間 + 等待(dai)時(shi)間

5、raise函(han)數(shu): 自己(ji)給(gei)自己(ji)發送信(xin)號(hao) raise(signo) == kill(getpid(), signo);

int raise(int sig);

成功:0,失敗非0值(zhi)

入(ru)參: 發(fa)送的信(xin)號

6、abort 函數:給自己(ji)發送(song)異常終止信號(hao) 6) SIGABRT 信號(hao),終止并產生core文件 void abort(void); //該函數無返回

kill函(han)數/命令產(chan)生信號

1、kill命(ming)令產生信號:kill -SIGKILL pid

2、kill函數:給指定(ding)(ding)進程發送指定(ding)(ding)信號(不一定(ding)(ding)殺(sha)死)

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

成功(gong):0;失敗:-1 (ID非法,信號(hao)非法,普通用(yong)戶殺(sha)init進(jin)程等權級問題(ti)),設置errno sig:不推薦直接(jie)使(shi)用(yong)數字,應使(shi)用(yong)宏名,因為不同操作系統(tong)信號(hao)編(bian)號(hao)可能不同,但(dan)名稱一致。

pid > 0: 發送信號給指定的進程。

pid = = 0: 發送信號給(gei) 與調用kill函(han)數進(jin)(jin)程屬于(yu)同一進(jin)(jin)程組的所(suo)有進(jin)(jin)程。

pid < 0: 取|pid|發(fa)給對應(ying)進程組。

pid = = -1:發(fa)送給進程有權限發(fa)送的系(xi)統(tong)中所有進程。

進(jin)(jin)(jin)程(cheng)組(zu):每個(ge)(ge)進(jin)(jin)(jin)程(cheng)都(dou)屬于一個(ge)(ge)進(jin)(jin)(jin)程(cheng)組(zu),進(jin)(jin)(jin)程(cheng)組(zu)是(shi)一個(ge)(ge)或多個(ge)(ge)進(jin)(jin)(jin)程(cheng)集合,他們相互關(guan)聯,共同完成一個(ge)(ge)實(shi)體任(ren)務,每個(ge)(ge)進(jin)(jin)(jin)程(cheng)組(zu)都(dou)有(you)一個(ge)(ge)進(jin)(jin)(jin)程(cheng)組(zu)長,默認進(jin)(jin)(jin)程(cheng)組(zu)ID與進(jin)(jin)(jin)程(cheng)組(zu)長ID

相同。

權(quan)限保護:super用(yong)(yong)戶(root)可(ke)以發送信號(hao)給任意用(yong)(yong)戶,普通用(yong)(yong)戶是(shi)不能向系統用(yong)(yong)戶發送信號(hao)的。 kill -9 (root用(yong)(yong)戶的pid) 是(shi)不可(ke)以的。同(tong)樣,普通用(yong)(yong)戶也不能向其他

普通用(yong)戶(hu)發(fa)送信號,終止其進程(cheng)。 只能(neng)向自己(ji)創建的(de)進程(cheng)發(fa)送信號。普通用(yong)戶(hu)基(ji)本規則(ze)是:發(fa)送者實(shi)際(ji)或有效用(yong)戶(hu)ID == 接收者實(shi)際(ji)或有效用(yong)戶(hu)ID

 

時序競態

設想如下場景:

欲睡覺(jue),定(ding)鬧鐘10分鐘,希望10分鐘后(hou)鬧鈴將自己喚醒。

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

異(yi)常(chang):鬧鐘(zhong)定(ding)好后,被喚走,外(wai)出勞動(dong),20分鐘(zhong)后勞動(dong)結束。回來(lai)繼續睡覺計(ji)劃,但勞動(dong)期(qi)間鬧鐘(zhong)已經響過,不會(hui)再將我(wo)喚醒。

時序問題分析

 回顧,借助pause和alarm實現的(de)mysleep函數。設想(xiang)如下時序(xu):

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

2. 調(diao)用alarm(1) 函數設定鬧(nao)鐘(zhong)1秒(miao)。

3. 函數(shu)調(diao)用剛結束,開始倒計(ji)時1秒。當(dang)(dang)(dang)前(qian)進程失去cpu,內核調(diao)度優(you)先級(ji)高(gao)的進程(有多個)取代當(dang)(dang)(dang)前(qian)進程。當(dang)(dang)(dang)前(qian)進程無法獲(huo)得(de)cpu,進入就緒態等待cpu。

4. 1秒(miao)后,鬧(nao)鐘超(chao)時(shi),內核向當(dang)前(qian)進程(cheng)發送(song)SIGALRM信號(自(zi)然定時(shi)法,與進程(cheng)狀態無

關),高優先級(ji)進程尚(shang)未執行完,當前進程仍(reng)處(chu)(chu)于(yu)就(jiu)緒態,信號(hao)無法處(chu)(chu)理(未決(jue))

5. 優(you)先級高的進程執(zhi)(zhi)行完,當前進程獲得cpu資(zi)源,內核調度回當前進程執(zhi)(zhi)行。

SIGALRM信(xin)號(hao)遞(di)達(da),信(xin)號(hao)設(she)置捕捉(zhuo),執行處理函數sig_alarm。

6. 信(xin)號處理函數(shu)執行結束,返回當前進程主控(kong)流程,pause()被調用掛起等待(dai)。(欲

等(deng)待alarm函數發送的SIGALRM信號將自己喚醒(xing))

7. SIGALRM信號已經處理完畢,pause不會等到。

解決時序問題

可以通(tong)過設置(zhi)屏蔽SIGALRM的方(fang)法來控制程序(xu)執行邏輯,但(dan)無論如何設置(zhi),程序(xu)都有(you)可能在“解除信號(hao)屏蔽”與“掛起(qi)等待信號(hao)”這個(ge)兩個(ge)操作(zuo)(zuo)間隙失(shi)去cpu資(zi)源。除非將這兩步驟(zou)合(he)并(bing)成一個(ge)“原子操作(zuo)(zuo)”。sigsuspend函數(shu)具備這個(ge)功能。在對(dui)時序(xu)要求嚴格的場

合下都應該使用sigsuspend替換(huan)pause。

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

sigsuspend函數(shu)調用期間(jian),進程(cheng)信號屏蔽字由其參數(shu)mask指定(ding)。

可(ke)將(jiang)某個信號(hao)(hao)(如SIGALRM)從臨時(shi)信號(hao)(hao)屏(ping)(ping)蔽(bi)(bi)字mask中(zhong)刪除,這(zhe)樣在(zai)調用sigsuspend時(shi)將(jiang)解(jie)除對該信號(hao)(hao)的屏(ping)(ping)蔽(bi)(bi),然后(hou)(hou)掛起等待,當sigsuspend返回(hui)時(shi),進程的信號(hao)(hao)屏(ping)(ping)蔽(bi)(bi)字恢復為原來的值。如果原來對該信號(hao)(hao)是屏(ping)(ping)蔽(bi)(bi)態,sigsuspend函數返回(hui)后(hou)(hou)仍然屏(ping)(ping)蔽(bi)(bi)該信號(hao)(hao)。

競態條(tiao)件,跟系統(tong)負(fu)載(zai)有很緊密(mi)的關系,體現出信(xin)號的不(bu)可靠(kao)性。系統(tong)負(fu)載(zai)越(yue)嚴重,信(xin)號不(bu)可靠(kao)性越(yue)強。

不(bu)可靠由其實(shi)現(xian)(xian)原理所致。信(xin)號(hao)是通過軟件方式實(shi)現(xian)(xian)(跟內核調度高度依賴(lai),延時(shi)(shi)性(xing)強),每(mei)次系統(tong)調用結束(shu)后,或中(zhong)斷處理處理結束(shu)后,需通過掃描(miao)PCB中(zhong)的未決信(xin)號(hao)集,來(lai)判斷是否應處理某個信(xin)號(hao)。當系統(tong)負載過重(zhong)時(shi)(shi),會出現(xian)(xian)時(shi)(shi)序混亂。

這種意外情況只能在(zai)編寫程序(xu)過程中(zhong),提早預見,主動規(gui)避,而無法通過gdb程序(xu)調試等其他(ta)手段(duan)彌(mi)補(bu)。且(qie)由于該錯誤(wu)不具規(gui)律性(xing),后期捕捉和重(zhong)現十分困難(nan)。

8、setitimer函數

設置定(ding)時器(鬧鐘(zhong))。 可(ke)(ke)代替alarm函數。精度微秒us,可(ke)(ke)以實現周(zhou)期(qi)定(ding)時。

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

成功:0;失敗:-1,設置errno

參數(shu):which:指定(ding)定(ding)時方式(shi)

① 自(zi)(zi)然(ran)定時(shi):ITIMER_REAL → 14)SIGLARM 計算(suan)自(zi)(zi)然(ran)時(shi)間

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

用cpu的(de)時間

③ 運行(xing)時計(ji)時(用(yong)(yong)戶+內核(he)):ITIMER_PROF → 27)SIGPROF 計(ji)算占用(yong)(yong)cpu及(ji)執行(xing)系(xi)

統調用的時間

信(xin)號集操作函(han)數:

內核通過讀(du)取未(wei)決信號(hao)集來(lai)判斷信號(hao)是(shi)否應被處(chu)理(li)。信號(hao)屏蔽字mask可以(yi)影響未(wei)決信號(hao)集。而我們可以(yi)在(zai)應用程序中自定(ding)義(yi)set來(lai)改變mask。已達到屏蔽指(zhi)定(ding)信號(hao)的目的。

信號集設定:

sigset_t set; // typedef unsigned long sigset_t;

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

成功:0;失敗:-1

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

1

成功:0;失敗:-1

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

成功:0;失敗:-1

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

成功:0;失敗:-1

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

集中

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

sigset_t類型的本質(zhi)是位圖。但不(bu)應該(gai)直接使(shi)用位操作,而應該(gai)使(shi)用上述(shu)函數,保(bao)證(zheng)

跨系(xi)統操作有效。

對(dui)比認知select 函數。

9、sigprocmask函數

用來(lai)屏蔽信(xin)號(hao)(hao)、解(jie)除屏蔽也使用該(gai)函數。其本質(zhi),讀取或修改進程的信(xin)號(hao)(hao)屏蔽字(PCB

中)

嚴格注(zhu)意,屏蔽信(xin)號(hao):只是將信(xin)號(hao)處(chu)理延后執(zhi)行(延至解除屏蔽);而(er)忽略(lve)表示(shi)將信(xin)號(hao)

丟處理。

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

參數:

set:傳入參數,是(shi)一個位(wei)圖,set中哪位(wei)置1,就表示(shi)當前進程屏蔽哪個信號。

oldset:傳(chuan)出參數,保存舊(jiu)的信(xin)號屏蔽(bi)集。

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

SIG_BLOCK: 當how設置為(wei)此值(zhi),set表(biao)示(shi)需要(yao)屏(ping)蔽的信(xin)號。相(xiang)當于 mask = mask|set

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

SIG_SETMASK: 當how設(she)置為(wei)此,set表(biao)示用于替代原始屏蔽及的新(xin)屏蔽集。相當于 mask = set若,調(diao)用sigprocmask解除了(le)對當前若干個(ge)信號(hao)的阻(zu)塞,則在sigprocmask返(fan)回

前,至(zhi)少將其中(zhong)一(yi)個信號遞達。

10、sigpending函數(shu)

讀(du)取當前進(jin)程的未決信號集

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

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

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

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

熱點文章推(tui)薦(jian)
華清學員就業榜單
高薪學(xue)員(yuan)經驗分享
熱點(dian)新聞推薦
前臺(tai)專線:010-82525158 企業培訓(xun)洽談(tan)專(zhuan)線(xian):010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,,京公海網安備11010802025203號

回到頂部