信號的產生

1)終端按鍵產生信號(與終端交互的進程)

Ctrl + c? → 2) SIGINT(終止/中斷)????? "INT" ----Interrupt

Ctrl + z? → 20) SIGTSTP(暫停/停止)? "T" ----Terminal 終端? 此時進程處于后臺運行

Ctrl + \? → 3) SIGQUIT(退出)????

2)硬件異常產生信號

除0操作?? → 8) SIGFPE (浮點數例外)? ? "F" -----float 浮點數。

非法訪問內存? → 11) SIGSEGV (段錯誤)

總線錯誤? → 7) SIGBUS(內存未對齊)

3kill函數/命令產生信號

注意:kill函數或命令產生信號并不一定是要殺死進程,信號的含義是根據編號(或宏)來決定的,不是kill本身的含義。

kill命令向指定進程發送指定信號: kill –SIGKILL pid? // 終止該進程,向該進程發送9號信號???

kill函數向指定進程發送指定信號:

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

作用:向指定進程(pid)發送指定信號(sig),指定信號最好用宏表示,不用編號,因為在不同類型的操作系統中,信號的編號可能會不一樣,用宏表示可以增強移植性。

返回值:成功0,失敗-1(ID非法;信號非法;普通用戶殺init進程等權級問題,即權限不夠)。

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

pid = 0:發送信號給與調用kill函數進程屬于同一進程組的所有進程(包括本身)。

pid < 0:取|pid|發給對應進程組。

pid = -1:發送給進程有權限發送的系統中所有進程(包括本身)。

進程組:每個進程都屬于一個進程組,進程組是一個或多個進程集合,他們相互關聯,共同完成一個實體任務,每個進程組都有一個進程組長,默認進程組ID與進程組長ID相同。

權限保護:super用戶(root)可以發送信號給任意用戶,普通用戶是不能向系統用戶發送信號的。同樣,普通用戶也不能向其他普通用戶發送信號,終止其進程。 只能向自己創建的進程發送信號。普通用戶基本規則是:發送者實際或有效用戶ID == 接收者實際或有效用戶ID

4raiseabort函數(系統調用產生,包括上面的kill函數)

raise函數:給當前進程發送指定信號(自己給自己發),則有:raise(signo) == kill(getpid(), signo);

#include <signal.h>

int raise(int sig); ??成功:0,失敗非0值

?

abort 函數:給自己發送異常終止信號 6) SIGABRT 信號,終止并產生core文件

#include <stdlib.h>

void abort(void);

5alarmsetitimer函數(軟件條件產生)

設置定時器(鬧鐘)。在指定seconds后,內核會給當前進程發送14)SIGALRM信號。進程收到該信號,默認動作終止(結束進程)。每個進程都有且只有唯一個定時器。

#include <unistd.h>

unsigned int alarm(unsigned int seconds);成功:返回舊鬧鐘剩余的秒數,即該進程上一次調用alarm函數后還剩下的秒數;或者返回0(第一次調用alarm函數的時候)。無失敗。

注意:alarm(0)表示取消鬧鐘,不是說0秒后終止進程,是取消鬧鐘。另外:定時與進程狀態無關(自然時間),就緒、運行、掛起(阻塞、暫停)、終止、僵尸等,無論進程處于何種狀態,alarm都計時。

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

alarm(5)返回0?? alarm(4)返回2??? alarm(5)返回0?? 緊隨著馬上的alarm(0)返回5,并且取消鬧鐘。

time命令。 time ./zsx 查看程序zsx執行的時間,時間由三部分組成:程序在進程系統空間運行的時間+用戶空間的時間+等待的時間(等待CPU、各種硬件資源等)=程序實際執行的時間。程序運行的瓶頸在于IO,優化程序,首選優化IO。

?

//練習:編寫程序,測試你使用的計算機1秒鐘能數多少個數。

#include <stdio.h>
#include <unistd.h>int main(void)
{int i;alarm(1);for(i = 0; ; i++)printf("%d\n", i);return 0;
}

#include <sys/time.h>

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

作用:類似alarm函數,有四點不一樣:1.setitimer函數對時間的計算方式有三種,用which參數指定,而alarm函數只有一種(自然時間);2. setitimer函數可以進行周期定時,即等待it_value時間后執行某一動作(收到信號),以后每隔it_interval時間再執行這一動作。而alarm函數只能實現等待it_value時間后執行某一動作(收到信號);3. setitimer函數可以精確到us級別,即其時間為tv_sec與tv_usec之和;4.返回值不一樣。

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

參數which指定定時方式:1.自然定時:ITIMER_REAL → 14SIGALRM 計算自然時間;2.虛擬空間計時(用戶空間):ITIMER_VIRTUAL → 26SIGVTALRM? ?? ?只計算進程占用cpu的時間;3.運行時計時(用戶+內核):ITIMER_PROF → 27SIGPROF ?計算占用cpu及執行系統調用的時間(即相對于自然時間,不包括等待時間)。

參數new_value為傳入參數,指定計時的大小,與alarm的參數作用一樣;

參數old_value為傳出參數,指定就舊鬧鐘剩余的秒數,作用類似alarm的返回值;結構體詳細描述如下:

struct itimerval {

struct timeval it_interval; /* next value */?? 下一次定時的值(間隔時間)

??? struct timeval it_value;??? /* current value */? 當前定時的值

};?? ??// it_intervalit_value設置為0表示清零操作,即取消定時。

struct timeval {

time_t???? ??tv_sec;???????? /* seconds */??? s

??? suseconds_t? ?tv_usec;??????? /* microseconds */? us

};

注意:每個進程都有且只有唯一個定時器。setitimer函數和alarm函數共用同一個定時器(鬧鐘)。

?

//練習: 使用setitimer函數實現alarm函數,重復計算機1秒數數程序。???

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>unsigned int my_alarm(unsigned int sec)    //實現alarm函數
{struct itimerval it, oldit;int ret;it.it_value.tv_sec = sec;it.it_value.tv_usec = 0;it.it_interval.tv_sec = 0;it.it_interval.tv_usec = 0;ret = setitimer(ITIMER_REAL, &it, &oldit);if (ret == -1) {perror("setitimer");exit(1);}return oldit.it_value.tv_sec;
}int main(void)
{int i;my_alarm(1);  //alarm(sec);for(i = 0; ; i++)printf("%d\n", i);return 0;
}

//拓展練習:測試it_intervalit_value這兩個參數的作用。

#include <stdio.h>
#include <sys/time.h>
#include <signal.h>void myfunc(int signo)
{printf("hello world\n");
}int main(void)
{struct itimerval it, oldit;signal(SIGALRM, myfunc);   //注冊SIGALRM信號的捕捉用戶處理函數,signal函數用于對信號進行注冊,真正捕捉該信號的是內核,內核捕捉該信號后就會去調用signal注冊時對應的用戶處理函數。    信號捕捉函數signal是一個典型的回調函數it.it_value.tv_sec = 5;it.it_value.tv_usec = 0;it.it_interval.tv_sec = 3;it.it_interval.tv_usec = 0;if(setitimer(ITIMER_REAL, &it, &oldit) == -1){perror("setitimer error");return -1;}while(1);return 0;
}

[root@localhost 01_signal_test]# ./setitimer1

hello world??? //5s

hello world?? ?//3s

hello world??? //3s

hello world?? ?//3s

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/385331.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/385331.shtml
英文地址,請注明出處:http://en.pswp.cn/news/385331.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

897. 遞增順序查找樹

給定一個樹&#xff0c;按中序遍歷重新排列樹&#xff0c;使樹中最左邊的結點現在是樹的根&#xff0c;并且每個結點沒有左子結點&#xff0c;只有一個右子結點。 示例 &#xff1a; 輸入&#xff1a;[5,3,6,2,4,null,8,1,null,null,null,7,9]5/ \3 6/ \ \2 4 8/ …

信號集操作函數

內核通過讀取未決信號集來判斷信號是否應被處理。信號屏蔽字mask可以影響未決信號集。而我們可以在應用程序中自定義set來改變mask。已達到屏蔽指定信號的目的。綜上&#xff1a;自定義信號集set&#xff08;也為一個字&#xff0c;64位&#xff09;通過信號集操作函數來改變信…

信號捕捉(signal、sigaction)

信號的基本屬性&#xff1a;軟中斷&#xff0c;由內核發送&#xff0c;內核處理。某個進程通過內核向另一個進程發送信號時&#xff08;引起信號產生的五個因素&#xff09;&#xff0c;另一個進程將會陷入內核進行中斷處理&#xff0c;未決信號集中相應信號置1&#xff0c;當遞…

1090 Highest Price in Supply Chain (25)(25 分)

A supply chain is a network of retailers&#xff08;零售商&#xff09;, distributors&#xff08;經銷商&#xff09;, and suppliers&#xff08;供應商&#xff09;-- everyone involved in moving a product from supplier to customer. Starting from one root suppli…

時序競態(競態條件)

產生原因&#xff1a;仍然以前文實現的sleep函數為例&#xff0c;如果進程在執行完alarm函數后&#xff0c;突然失去CPU&#xff0c;被阻塞等待&#xff08;這是有可能的&#xff0c;進程在執行過程中&#xff0c;若非原子操作&#xff0c;都有可能隨時失去CPU&#xff09;&…

1106 Lowest Price in Supply Chain (25)

A supply chain is a network of retailers&#xff08;零售商&#xff09;, distributors&#xff08;經銷商&#xff09;, and suppliers&#xff08;供應商&#xff09;-- everyone involved in moving a product from supplier to customer. Starting from one root suppli…

【Leetcode | 順序刷題 】二分查找目錄

二分查找序號題號129. 兩數相除 50. Pow(x, n) 69. x 的平方根

sigsuspend函數(mysleep函數的改進)

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

【Leetcode | 順序刷題】數學目錄

序號題號1 7. 整數反轉 28. 字符串轉換整數 (atoi)39. 回文數443. 字符串相乘

全局變量的異步I/O問題

全局變量的異步I/O問題同樣屬于時序競態問題&#xff0c;其本質就是多個進程或者同一個進程中的多個時序&#xff08;如主控程序和信號捕捉時的用戶處理函數&#xff09;對同一個變量進行修改時&#xff0c;它們的執行順序不一樣就會導致該變量最終的值不一樣&#xff0c;從而產…

【Leetcode | 03】String

字符串目錄序號題號33. 無重復字符的最長子串 151. 翻轉字符串里的單詞

可/不可重入函數

一個函數在被調用執行期間&#xff08;尚未調用結束&#xff09;&#xff0c;由于某種時序&#xff08;遞歸或者處理信號捕捉時等情況&#xff09;又被重復調用&#xff0c;稱之為“重入”。根據函數實現的方法可分為“可重入函數”和“不可重入函數”兩種。看如下程序。 可以看…

【Leetcode | 順序刷題】雜項目錄

序號題號類別1136. 只出現一次的數字位運算2137. 只出現一次的數字 II位運算3 260. 只出現一次的數字 III 位運算4191. 位1的個數位運算5231. 2的冪位運算6342. 4的冪位運算7 338. 比特位計數 位運算8405. 數字轉換為十六進制數位運算9371. 兩整數之和位運算10401. 二進制手表位…

SIGCHLD信號

&#xff08;1&#xff09;SIGCHLD信號產生的條件 1.子進程終止時會向父進程發送SIGCHLD信號&#xff0c;告知父進程回收自己&#xff0c;但該信號的默認處理動作為忽略&#xff0c;因此父進程仍然不會去回收子進程&#xff0c;需要捕捉處理實現子進程的回收&#xff1b; 2.子…

信號傳參

&#xff08;1&#xff09;發送信號傳參 前面已經知道從一個進程向另一個進程發送信號可以使用kill函數&#xff0c;但是kill函數在向進程發送信號的時候不能攜帶除了信號以外的其他信息&#xff0c;這時可以使用與kill相對應的sigqueue函數&#xff0c;該函數也是向一個進程發…

【Leetcode | 52】257. 二叉樹的所有路徑

給定一個二叉樹&#xff0c;返回所有從根節點到葉子節點的路徑。 說明: 葉子節點是指沒有子節點的節點。 示例: 輸入: 1 / \ 2 3 \ 5 輸出: ["1->2->5", "1->3"] 解釋: 所有根節點到葉子節點的路徑為: 1->2->5, 1->3 解法一&a…

623. 在二叉樹中增加一行

給定一個二叉樹&#xff0c;根節點為第1層&#xff0c;深度為 1。在其第 d 層追加一行值為 v 的節點。 添加規則&#xff1a;給定一個深度值 d &#xff08;正整數&#xff09;&#xff0c;針對深度為 d-1 層的每一非空節點 N&#xff0c;為 N 創建兩個值為 v 的左子樹和右子樹…

終端的概念

操作系統接口&#xff1a;用戶接口和程序接口。用戶接口分為聯機用戶接口和脫機用戶接口。脫機用戶接口出現在早期的批處理系統中&#xff08;將作業提前交給操作系統&#xff0c;作業完成的過程中用戶無法交互&#xff09;&#xff1b;聯機用戶接口即為終端&#xff08;所有輸…

終端的啟動流程

在Linux操作系統啟動時&#xff0c;首先加載的進程就是init進程&#xff08;ID為1&#xff09;&#xff0c;其余進程都是init進程產生的&#xff08;fork&#xff0c;然后exec金蟬脫殼&#xff09;&#xff0c;因此系統中所有進程都可以看成是init進程的子孫進程。可以通過ps a…

進程組(作業)

&#xff08;1&#xff09;概念和特性 進程組&#xff0c;也稱之為作業。BSD于1980年前后向Unix中增加的一個新特性。代表一個或多個進程的集合。每個進程都屬于一個進程組。在waitpid函數和kill函數的參數中都曾使用到。操作系統設計的進程組的概念&#xff0c;是為了簡化對多…