Linux程序通訊 訊號

2021-05-24 02:10:44 字數 4948 閱讀 7973

1.程序

在介紹訊號的概念之前,先簡單的介紹一下程序的概念:

程序可以理解為一段正在執行的程式,它包括以下三個部分內容:

(1)一段正在執行的程式

(2)與該段程式相關聯的全部資料(資料空間,記憶體,緩衝區)。

(3) 程式計數器(pc).

2.訊號

可以這麼理解訊號,訊號本身不是訊息,它表達的內容才是訊息。 linux訊號是軟體中斷所提供的用於非同步處理事件的一種機制。事件可以來自系統外部,或者來自程式或者是核心。

核心處理訊號有以下幾種方式:

(1)忽略此訊號

即不採取任何動作。但有兩種訊號不能忽略,sigkill,sigstop,這是系統殺掉或停止程序的可靠方法。如果乙個程序能夠忽略此訊號,那麼將能夠不無法被殺掉或停止。這是不允許的。

(2)捕獲以及處理訊號

核心可以暫停當前程序的執行路徑,跳到訊號處理函式的入口處,執行訊號處理,處理完畢後再回到暫停之處。

sigint,sigterm就是兩個可以**獲的訊號。sigint對應的ctrl+c,sigterm可以在終止前進行必要的處理。

(3)執行預設的動作

此動作取決於被送出的訊號,預設的動作通常是終止程序。

3.訊號識別符號

每個訊號都以乙個sig開頭。每個訊號會被關聯到乙個整數值。 訊號的編號始於1,而且繼續向上線性增長,總共大約有64個訊號值,前32種是不可靠訊號,後32種是可靠訊號。即前32種訊號有可能發生訊號丟失,而後32種不會。對於不可靠訊號而言,當到達多次時,核心只會註冊一次。而可靠訊號會註冊多次,形成訊號佇列。

4. 訊號的用途

一般說來,訊號主要用於以下三個地方:

(1)使用者: 使用者通過輸入ctrl+c,來請求產生核心訊號

(2)核心:當核心執行出錯時,核心會給程序傳送乙個訊號,如非法記憶體位址訪問。除此之外,核心也通過訊號機制來通知事件的發生。

(3)程序: 乙個程序可以通過kill函式給另外乙個程序傳送訊號,即訊號用於程序間通訊。

所以,程序通訊就把程序與訊號聯絡起來了。

接收訊號的程序與傳送訊號的程序的所有都必須相同。

5.程序與訊號所用的介面函式

int wait(&status);

理解wait函式,必須從以下三個方面進行剖析:

(1) wait函式是用於父程序與子程序之間的同步,當父程序呼叫wait函式時,會阻塞在那裡

(2) 當子程序成功返回時,wait函式返回的是子程序的pid,如果失敗返回-1,並將errno變數裡面存放echild

(3) 如果status為空的話,則不返回任何資訊。否則,status所指向的位址用於返回程序的狀態資訊。是乙個整數值,這個狀態資訊不僅包括子程序結束時的返回值,即exit(1). 以及是否成功返回。當呼叫wait函式時,將徹底銷毀子程序。

int waitpid(pid_t pid,*status, int options);

這個函式與wait函式的功能差不多。

第乙個引數:

如果pid>0,那麼waitpid等待的是指定程序的pid,如果這個程序結束,那麼waitpid返回這個程序的pid.

如果pid=0,那麼waitpid等待同一組中的任一程序結束。

如果pid=-1,那麼waitpid等待系統中任何乙個程序結束。

如果pid<-1,那麼waitpid等待程序組號絕對值為pid的任何乙個程序結束。

waitpid只要檢測到乙個程序結束時,它便會返回。

status同上面的status.

options:

(1)如果不使用options,將option=0

(2) options可選擇的引數有wnohang,wuntraced

如果使用了wnohang,即使子程序沒有退出,父程序也不會被阻塞。wuntraced是用於除錯資訊的。

int kill(pid_t pid,int sig);

功能: kill函式是向乙個指定程序傳送訊號。

引數:如果pid>0,那麼kill函式會將訊號傳送給指定的程序

如果pid=0,那麼kill函式會將訊號傳送給同一程序組中的每個程序

如果pid=-1,那麼kill函式會將訊號傳送給呼叫的程序有權傳送的每個程序(許可權:乙個具有cap_kill能力的程序,通常為root所擁有,能夠可以傳送乙個訊號給任何程序。若不具備此能力,那麼傳送程序的使用者id必須等於接收端的使用者的id,也就是乙個使用者只能傳送乙個訊號給自己的乙個程序)。

如果pid<-1,那麼kill函式會傳送給程序組號的絕對值為pid中的每個程序

返回值: 執行成功後,kill()返回0,只要有訊號被送出,此呼叫就會被視為成功。執行失敗後,會返回-1,並且將errno設定為下列乙個值:

einval

signo指定了無效的訊號

eperm

進行呼叫的程序的許可權不足以將乙個訊號傳送給任何請求的程序

esrch

pid所指定的程序或程序組不存在,或者是乙個僵死程序

raise(signo)

這個函式是程序給自己傳送乙個訊號 。

相當於kill(getpid(),signo).

相關的巨集:

wifexited(status) 如果程序呼叫exit正常退出時,該值為非0

wexitedstatus(status) 如果wifexited(status)非0時,那麼該函式返回exit(3)結束設定的引數值。這裡會返回3

wifsignaled(status) 如果子程序是因為接收到訊號而退出時,返回非0

wtermsig(status) 如果wifsignaled非0時,返回訊號**值。

下面是與訊號相關的例子:

示例1:

/**wait(&status)與kill(pid_t pid,int sig);

(1)當wait函式呼叫時,父程序就會被阻塞在那裡

(2)wait成功返回的是子程序的pid,如果失敗就返回-1

(3)wait函式將結束的子程序的狀態存於status中去,這個狀態包括子程序的返回值以及是否成功返回

kill

kill函式是將指定訊號傳遞到指定的程序中去

pid>0 將指定的訊號sig傳遞到程序號為pid的程序中去

pid=0 將指定訊號sig傳遞到與目前程序相同的程序組中的所有程序

pid=-1 將訊號傳遞給系統內的所有程序

pid<-1 將訊號傳遞給程序組號的絕對值為pid的所有程序

kill(getpid(),sig);//程序向自身傳送訊號

**/#include

#include

#include

#include

int main()

else if(childpid==0)

else

else }}

}執行結果為:

child proccess

child proccess receive signal 6

分析: 父程序在睡眠1秒後,傳送sigabrt訊號,然後在wait處阻塞,等待子程序終止返回。只要有任何乙個子程序退出時,父程序就會在wait處返回。

示例2:

/**wait(&status)與waitpid(pid_t pid,*status,int options)

(1)當父程序呼叫wait函式時,父程序被阻塞在那裡

(2)wait函式返回值是子程序的pid,如果失敗,則返回-1,並將echild存入到errno

(3)wait函式將子程序結束時的狀態存入到status中去,將子程序徹底銷毀,銷毀程序表項

waitpid與wait的功能是相同的,不過多了幾個引數

pid(1)pid>0 只等待pid的程序結束,如果其它程序結束時,waitpid還會被阻塞,直到指定pid的程序結束為止

(2)pid=-1等待任何乙個子程序退出,此時wait與waitpid的功能是一樣的

(3)pid=0等待同乙個程序組中的任何乙個程序退出

(4)pid<-1 等待乙個指定程序組中的任何程序退出,這個程序組的pid等於pid的絕對值

options

(1)如果不使用options,將options設定為0

(2)options可取引數 wnohang,wuntraced

如果使用了wnohang,即使子程序沒有退出,父程序也不會阻塞,依舊執行下去

而wutraced是用於跟蹤除錯的資訊

**/#include

#include

#include

#include

#include

int main()

childpid1=fork();

if(childpid1==0)

else

printf("等待子程序返回/n");

}while(pr==0);

if(wifexited(status))

else }}

}執行結果為:

pr=0等待子程序返回

pr=0 等待子程序返回

pr=0等待子程序返回

pr=0等待子程序返回

pr=0等待子程序返回

pr=15443等待子程序返回

子程序傳送的訊號量為:6

分析: 該程式中有兩個子程序,乙個是正常退出,另乙個是用raise函式向自己傳送訊號,終止自己。waitpid只等待第乙個子程序結束。

即使第二個子程序先結束也不理。

waitpid函式中第三個引數是wnohang,即子程序沒有終止時,也不會阻塞父程序,但此時waitpid的返回值會為0.

可以用 man waitpid看看它的使用及返回值。

這篇文章中簡單的介紹了程序與訊號的使用情況。總之,記住兩點:

(1) 程序會阻塞在wait函式那裡,waitpid 的wnohang可以讓父程序不阻塞。

(2) 程序用kill函式可以向另外乙個程序傳送訊號。raise向自身傳送訊號。

wait(&status)=waitpid(-1,&status,0);

kill(getpid(),signo)=raise(signo);

Linux程序通訊 訊號通訊

訊號 signal 機制是unix系統中最為古老的程序間通訊機制,很多條件可以產生乙個訊號 1 當使用者按某些按鍵時,產生訊號 2 硬體異常產生訊號 除數為0 無效的儲存訪問等等。這些情況通常由硬體檢測到,將其通知核心,然後核心產生適當的訊號通知程序,例如 核心對正訪問乙個無效儲存區的程序產生乙個s...

Linux 程序通訊 訊號

linux 程序通訊 訊號 模擬 乙個程序收到訊號與乙個處理器收到乙個中斷請求可以說一樣的,訊號是非同步的,乙個程序不必通過任何操作來等待訊號的到達,事實上,程序也不知道訊號是什麼時候到達。常見訊號 sighup 從終端發出的訊號 sigint 來自鍵盤中斷訊號 sigkill 訊號結束接受訊號程序...

linux程序通訊 訊號

1.訊號的分類,常用的幾種訊號 訊號的分類 可靠性方面 可靠訊號和不可靠訊號 與時間上的關係 實時訊號與非實時訊號 常見的訊號 sighup 從終端上發出的結束訊號 sigint 來自鍵盤的中斷訊號 ctrl c sigkill 該訊號結束接收訊號的程序,殺死程序 sigterm kill 命令發出...