linux信號函數
A. linux的kill函數和SIGUSR1信號。
對於這個信號而言,沒有信號響應函數的話,進程應該會異常終止,對於系統已有的信號一般都是有默認處理的,具體的我有點記不得了,搜下其實就知道了.我在網上找了下各信號默認處理方式,你看看吧,對你有沒有用
信號名稱 信號說明 默認處理
SIGABRT 由程序調用 abort時產生該信號。 程序異常結束。 進程終止並且產生core文件
SIGALRM timer到期, 有alarm或者setitimer 進程終止
SIGBUS 匯流排錯誤,地址沒對齊等。取決於具體硬體。 結束終止並產生core文件
SIGCHLD 進程停止或者終止時,父進程會收到該信號。 忽略該信號
SIGCONT 讓停止的進程繼續執行 繼續執行或者忽略
SIGFPE 算術運算異常,除0等。 進程終止並且產生core文件。
SIGHUP 終端關閉時產生這個信號 進程終止
SIGILL 代碼中有非法指令 進程終止並產生core文件
SIGINT 終端輸入了中斷字元ctrl+c 進程終止
SIGIO 非同步I/O,跟SIGPOLL一樣。 進程終止
SIGIOT 執行I/O時產生硬體錯誤 進程終止並且產生core文件
SIGKILL 這個信號用戶不能去捕捉它。 進程終止
SIGPIPE 往管道寫時,讀者已經不在了,或者往一個已斷開數據流socket寫數據。 進程終止
SIGPOLL 非同步I/O,跟SIGIO一樣。 進程終止
SIGPROF 有setitimer設置的timer到期引發 。 進程終止
SIGPWR Ups電源切換時 進程終止
SIGQUIT Ctrl+\,不同於SIGINT,這個是會產生core mp文件的。 進程終止並且產生core文件
SIGSEGV 內存非法訪問,默認列印出segment fault 進程終止並且產生core文件
SIGSTOP 某個進程停止執行,該信號不能被用戶捕捉。 進程暫停執行
SIGSYS 調用操作系統不認識的系統調用。 進程終止並且產生core文件
SIGTERM 有kill函數調用產生。 進程終止
SIGTRAP 有調試器使用,gdb 進程終止並且產生core文件
SIGTSTP Ctrl+z,掛起進程。 進程暫停
SIGTTIN 後台程序要從終端讀取成數據時。 進程暫停
SIGTTOU 後台終端要把數據寫到終端時。 進程暫停
SIGURG 一些緊急的事件,比如從網路收到帶外數據。 忽略
SIGUSR1 用戶自定義信號 進程終止
SIGUSR2 用戶自定義信號 進程終止
SIGVTALRM 有setitimer產生。 進程終止
B. Linux 環境下的C語言, 關於 kill 發送信號和 signal() 函數, 具體問題在以下代碼的注釋處
pause()會令目前的進程暫停(進入睡眠狀態), 直到被信號(signal)所中斷。
當50信號觸動了,pause將退出睡眠狀態,執行printf和return
C. linux c signal函數
是第二次調用的時候輸出的,第一次調用只是綁定了SIGUSR1的信號處理函數,不會進入該處理函數
為什麼會有這樣的輸出呢?
signal函數是將信號與處理函數進行綁定,成功綁定則返回綁定之前的信號處理函數。那麼來看看你的代碼,第一次調用將sig_fun1綁定,無輸出;第二次調用將sig_fun2綁定,也就是把sig_fun1替換下來,並且你還調用了它,參數為30,所以會有那樣的輸出。
該如何改呢?
其實你並沒有涉及到linux的信號處理機制,光綁定是不夠的,還需要發信號給它,才能真正進入信號處理過程。給你一個示例代碼吧
#include<signal.h>
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
void sig_fun2(int signo)
{
printf("in sig_fun2:%d\n", signo);
}
void sig_fun1(int signo)
{
printf("in sig_fun1:%d\n", signo);
}
int main()
{
unsigned long i;
if (signal(SIGUSR1, sig_fun1) == SIG_ERR)
{
printf("signal fun1 error\n");
exit(1);
}
sleep(15);
(signal(SIGUSR1, sig_fun2))(30);
sleep(15);
printf("done\n");
return 0;
}
/****************************C 代碼完,下面是如何運行***************************/
首先編譯,假設生成可執行程序為test
然後運行,我用的是後台運行: nohup ./test>output.txt &
注意,這種方法要將輸出重定向到文件output.txt(名字無所謂),然後你會看到一個數字,就是pid進程號
最後,在15秒之內發送信號:kill -SIGUSR1 進程號
現在你就可以打開output.txt看輸出結果了。如果用sleep的話會被打斷,所以只有兩個輸出加上替換處理函數時的輸出共3個,也可以換成 int n=15;while(n--)sleep(1);
-------------------------------------------------------------
怎麼樣,加分吧
-------------------------------------------------------------
1.我就是想問第二次綁定sig_fun2的時候,調用了第一次綁定的sig_fun1么?
調用了, (signal(SIGUSR1, sig_fun2))(30);就是這一句, signal(SIGUSR1, sig_fun2)是個函數指針,你這樣寫就是調用它了,但是這和信號處理沒關系,寫成signal(SIGUSR1, sig_fun2);就可以了
這就是你所說的成功則返回綁定之前的函數???
對
那當時綁定sig_fun1的時候,返回之前的處理函數是什麼??
這個就是系統默認的了,比如SIGINT就是你ctrl+c取消程序執行發送的信號,它的處理函數就是結束程序的一系列動作,不過SIGUSR1是留給用戶自定義的信號,系統默認應該是啥也不做的一個函數,例如void fun(int signo){},你也可以第一次綁定的時候就調用試試看對不對
2.還有我在看signal函數定義的時候,void(//...)(int) 最後傳入的這個int整形參數就是我們自定義sig_fun()中所接收的30么??我看例子裡面有的signal(SIGINT,myfunc);也沒有帶參數啊,搞不懂
是你理解錯了,signal函數只是綁定,沒涉及到調用綁定函數,不用帶參數,信號處理函數不是像你這樣調用的。callback回調你知道吧,就是先做好一個函數或過程放著,事件觸發的時候才調用。那個30是你用普通函數調用的方式時的參數,跟信號處理一點關系也沒有,你用60,70也沒半毛錢關系。我猜你是想要調用信號處理函數,然後迷糊了,其實我上面說的「kill -SIGUSR1 進程號」就是觸發程序調用該處理函數的信號,這和kill -9 殺死進程一個道理,只不過處理函數不同,結果不一樣。ctrl+c也可以用信號的方式發送,kill -2 進程號,或者 kill -SIGINT 進程號
另外,站長團上有產品團購,便宜有保證
D. linux鍑芥暟鏄浠涔堟剰鎬濓紵
Linux鍑芥暟鏄浠涔堟剰鎬濓紵 鍦↙inux鎿嶄綔緋葷粺涓錛屽嚱鏁版槸涓縐嶅彲閲嶇敤鐨勪唬鐮佸潡錛屽畠璐熻矗鎵ц岀壒瀹氱殑浠誨姟騫惰繑鍥炵粨鏋溿侺inux鍑芥暟鍙浠ユ帴鍙楀弬鏁板拰榪斿洖鍊礆紝浠ヤ究鍦ㄧ▼搴忎腑浼犻掍俊鎮鍜屼慨鏀瑰彉閲忋傝繖縐嶄唬鐮佸嶇敤鐨勬柟寮忓彲浠ヤ嬌紼嬪簭鏇村姞妯″潡鍖栵紝騫朵笖鍑忓皯浠g爜鐨勯噸澶嶄功鍐欍
濡備綍浣跨敤Linux鍑芥暟錛熻佷嬌鐢↙inux鍑芥暟錛屾偍闇瑕佺紪鍐欎竴涓鍑芥暟瀹氫箟錛屽寘鎷鍑芥暟鍚嶇О銆佸弬鏁板垪琛ㄤ互鍙婅佹墽琛岀殑鎸囦護搴忓垪銆傜劧鍚庯紝鎮ㄥ彲浠ュ湪紼嬪簭鐨勪富瑕侀儴鍒嗕腑璋冪敤鍑芥暟騫朵紶閫掑弬鏁般侺inux鎻愪緵浜嗚稿氬父鐢ㄧ殑鍑芥暟錛屽寘鎷鏂囦歡I/O銆佺郴緇熻皟鐢ㄥ拰瀛楃︿覆鎿嶄綔絳夈傛偍鍙浠ヤ嬌鐢ㄨ繖浜涙爣鍑嗗嚱鏁幫紝涔熷彲浠ョ紪鍐欒嚜宸辯殑鑷瀹氫箟鍑芥暟鏉ュ疄鐜扮壒瀹氱殑浠誨姟銆
Linux鍑芥暟鐨勪紭鍔挎槸浠涔堬紵 Linux鍑芥暟鐨勪紭鍔挎槸璇ュ嚱鏁扮殑浠g爜鍙浠ュ湪紼嬪簭涓澶氭′嬌鐢錛屼互鑺傜渷緙栫▼鏃墮棿銆傛ゅ栵紝浣跨敤鍑芥暟榪樺彲浠ュ炲姞浠g爜鐨勫彲璇繪у拰鍙緇存姢鎬с傜敱浜庡畠浠鐨勬ā鍧楀寲璁捐★紝瀹冧滑鍙浠ュ緢瀹規槗鍦板垎綾匯佹祴璇曞拰淇鏀廣侺inux鍑芥暟榪樻湁鍔╀簬闄嶄綆紼嬪簭涓鐨勯敊璇鐜囷紝鍥犱負瀹冧滑鍙浠ョ嫭絝嬪湴榪涜屾祴璇曞拰楠岃瘉銆傚洜姝わ紝Linux鍑芥暟鏄緙栧啓楂樿川閲忓彲闈犵殑緋葷粺鐨勫叧閿閮ㄥ垎涔嬩竴銆
E. 濡備綍鍦↙inux涓閫氳繃semget鍜宻emctl鍑芥暟鍒嗛厤騫墮噴鏀句俊鍙烽噺錛
Linux 緋葷粺涓錛屼俊鍙烽噺鐨勭$悊閫氳繃 semget 鍜 semctl 榪欎袱涓緋葷粺璋冪敤鏉ュ畬鎴愶紝瀹冧滑鐨勪綔鐢ㄧ被浼間簬 shmget 鍜 shmctl 瀵瑰叡浜鍐呭瓨鐨勫勭悊銆傝佷嬌鐢ㄤ俊鍙烽噺錛屼綘闇瑕侀栧厛璋冪敤 semget 鍑芥暟錛屼紶鍏ュ弬鏁板寘鎷淇″彿閲忕粍鐨勯敭鍊箋佷俊鍙烽噺鐨勬暟閲忎互鍙婃潈闄愭爣璇嗐傞敭鍊肩敤浜庡敮涓鏍囪瘑淇″彿閲忕粍錛屽嵆浣胯繘紼嬮鍑猴紝淇″彿閲忎篃浼氬湪緋葷粺涓鎸佷箙瀛樺湪銆傝幏鍙栧凡瀛樺湪鐨勪俊鍙烽噺鏃訛紝鍙浠ヤ紶鍏0浣滀負緇勫歸噺銆
淇″彿閲忕殑鐢熷懡鍛ㄦ湡闇瑕佹墜鍔ㄧ$悊錛屽綋鏈鍚庝竴涓浣跨敤淇″彿閲忕殑榪涚▼閫鍑烘椂錛岄渶瑕佽皟鐢 semctl 鍑芥暟鏉ュ垹闄や俊鍙烽噺緇勩傝繖涓鍑芥暟闇瑕佸洓涓鍙傛暟錛氫俊鍙烽噺緇勬爣璇嗙︺佽佹搷浣滅殑淇″彿閲忕紪鍙鳳紙鍦ㄨ繖涓渚嬪瓙涓鏄1錛夈佸父閲 IPC_RMID 鍜屼竴涓 union semun 綾誨瀷鐨勭粨鏋勪綋錛堝疄闄呮搷浣滀腑蹇界暐錛夈傚垹闄ゆ搷浣滆佹眰璋冪敤鑰呬笌淇″彿閲忕粍鍒涘緩鑰呮潈闄愮浉鍚岋紝鎴栬呮嫢鏈 root 鏉冮檺銆備笌 shmget 涓嶅悓錛屽垹闄や俊鍙烽噺緇勪細絝嬪嵆閲婃斁緋葷粺璧勬簮銆
鍦ㄤ唬鐮佸眰闈錛屽備唬鐮 5.2錛坰em_all_deall.c錛夋墍紺猴紝鏈変袱涓鍏抽敭鍑芥暟錛氫竴涓鐢ㄤ簬鍒嗛厤浜屽厓淇″彿閲忥紙binary_semaphore_allocation錛夛紝閫氳繃 semget 鍑芥暟鑾峰彇鎴栧壋寤猴紱鍙︿竴涓鐢ㄤ簬閲婃斁浜屽厓淇″彿閲忥紙binary_semaphore_deallocate錛夛紝浣跨敤 semctl 鍑芥暟榪涜屽垹闄ゆ搷浣滐紝紜淇濊祫婧愮殑姝g『閲婃斁銆
鍒嗛厤浜屽厓淇″彿閲忥細 int binary_semaphore_allocation (key_t key, int sem_flags)錛岃繑鍥 semget 鐨勭粨鏋滐紝濡傛灉闇瑕佸垯鍒涘緩淇″彿閲忋
閲婃斁浜屽厓淇″彿閲忥細 int binary_semaphore_deallocate (int semid)錛岃皟鐢 semctl 鍑芥暟鍒犻櫎淇″彿閲忥紝鍙傛暟鍖呮嫭淇″彿閲忕粍鏍囪瘑絎﹀拰甯擱噺 IPC_RMID銆
鎵╁睍璧勬枡
Linux 鎻愪緵鐨勫悇縐嶇郴緇熻皟鐢ㄦ潵瀹炵幇涓涓鍏鋒湁涓ょ嶇姸鎬佺殑淇″彿閲忥紙binary semaphore錛夈
F. linux系統上信號發送和信號接收講解
用於進程間通信,通信機制由操作系統保證,比較穩定。
在linux中可以通過kill -l查看所有信號的類型。
kill -信號類型 進程ID
int kill(pid_t pid, int sig);
入參pid :
pid > 0: 發送信號給指定的進程。
pid = 0: 發送信號給 與調用kill函數進程屬於同一進程組的所有進程。
pid < 0: 取|pid|發給對應進程組。
pid = -1:發送給進程有許可權發送的系統中所有進程。
sig :信號類型。
返回值 :成功:0;失敗:-1 (ID非法,信號非法,普通用戶殺init進程等權級問題),設置errno
以OpenHarmony源碼為例,應用ANR後,AbilityManagerService會通知應用mp堆棧信息,就是通過信號量做的。
頭文件位置 :
include <signal.h>
函數解釋 :
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
當接收到指定的信號signum時,就會跳轉到參數handler指定的函數執行。其中handler的入參是信號值。
函數原型 :
signum參數指出要捕獲的信號類型,act參數指定新的信號處理方式,oldact參數輸出先前信號的處理方式(如果不為NULL的話)。
sigaction結構體
sa_handler 信號處理函數
sa_mask 在處理該信號時可以暫時將sa_mask 指定的信號集擱置
sa_flags 指定一組修改信號行為的標志。 它由以下零個或多個的按位或組成
SA_RESETHAND:當調用信號處理函數時,將信號的處理函數重置為預設值SIG_DFL
SA_RESTART:如果信號中斷了進程的某個系統調用,則系統自動啟動該系統調用
SA_NODEFER :一般情況下, 當信號處理函數運行時,內核將阻塞該給定信號。但是如果設置了 SA_NODEFER標記, 那麼在該信號處理函數運行時,內核將不會阻塞該信號
sa_restorer 是一個替代的信號處理程序,當設置SA_SIGINFO時才會用它。
相關函數
int sigemptyset( sigset_t *set);
sigemptyset()用來將參數set信號集初始化並清空。
執行成功則返回0,如果有錯誤則返回-1。
完整示例