1. 程式人生 > >【嵌入式Linux C程式設計】Linux程序間通訊——IPC

【嵌入式Linux C程式設計】Linux程序間通訊——IPC

程序間通訊的作用:資料傳輸; 資源共享; 通知事件; 程序控制。

管道通訊

管道是單向的,先進先出(FIFO)。將一個程序的輸出和另一個程序的輸入連在一起。

輸出程序在管道尾部寫入資料,輸入程序在管道頭部接受資料。資料在被讀出後,將從管道中清楚,其他程序再也無法讀取到該資料。程序試圖讀空管道時,程序將阻塞。同樣,管道已經滿時,程序再試圖向管道寫入資料,程序將阻塞。

管道分為無名管道有名管道

無名管道適用於父子程序; 有名管道適用於任意兩個程序。

無名管道(PIPE)建立:
                int pipe(int filedis[2]);
    當一個管道建立時,它會建立兩個檔案描述符:
filedis[0] 用於讀管道,

filedis[1] 用於寫管道。

管道用於不同程序間通訊。通常先建立一個管道,再通過fork函式建立一個子程序,該子程序會繼承父程序所建立的管道。

有名管道(FIFO)建立:

                int mkfifo(const char * pathname, mode_t mode);

                 該函式會依據pathname建立一個特殊的FIFO檔案,該檔案必須是不存在的,而引數mode是該檔案的許可權。

訊號通訊

命令:kill -l 可以列出全部訊號(signal)。

下面是幾種常見的訊號:
 SIGHUP: 從終端上發出的結束訊號
 SIGINT: 來自鍵盤的中斷訊號(Ctrl-C)
 SIGKILL:該訊號結束接收訊號的程序
 SIGTERM:kill 命令發出的訊號
 SIGCHLD:標識子程序停止或結束的訊號

 SIGSTOP:來自鍵盤(Ctrl-Z)或除錯程式的停止執行訊號

當一個訊號出現時,會以三種方式進行處理:

1.忽略此訊號,大多數訊號用這種方式處理,除了SIGKILL\SIGSTOP,因為這兩個訊號向超級使用者提供了一種終止或停止進場的方法;

2.執行使用者希望的動作,通知核心在某種訊號發生時,呼叫一個使用者函式。在使用者函式中,執行使用者希望的處理;

3.執行預設的操作,對大多數訊號的系統預設動作是終止該程序。

傳送訊號的主要函式有kill和raise。

Kill既可以向自身傳送訊號,也可以向其他程序傳送訊號。與kill函式不同的是,raise函式是向程序自身傳送訊號。

   int kill(pid_t pid, int signo);//向pid程序傳送signo
   int raise(int signo);//向自己傳送signo

共享記憶體

共享記憶體是被多個程序共享的一部分實體記憶體。共享記憶體是程序間共享資料的一種最快的方法。

實現共享記憶體的步驟:

1.建立共享記憶體(實體記憶體),shmid = shmget(key_t key, int size, int shmflg );

2.將共享記憶體對映到程序的虛擬記憶體中,shmadd = shmat(int shmid, char *shmaddr, int flag);flag通常為‘0’;

3.使用對映的記憶體;

4.接觸對映,shmdt(char *shmaddr);

5.銷燬共享記憶體,shmctl(int shmid);

訊息佇列

訊息佇列就是一個訊息的連結串列.可以把訊息看作一個記錄,具有特定的格式.程序可以向中按照一定的規則新增新訊息;另一些程序則可以從訊息佇列中讀走訊息。

目前主要有兩種型別的訊息佇列:POSIX訊息佇列以及系統V訊息佇列,系統V訊息佇列目前被大量使用。
系統V訊息佇列是隨核心持續的,只有在核心重起或者人工刪除時,該訊息佇列才會被刪除。

訊息佇列的核心持續性要求每個訊息佇列都在系統範圍內對應唯一的鍵值,所以,要獲得一個訊息佇列的描述字,必須提供該訊息佇列的鍵值。

建立訊息佇列

#define MSGKEY 1212

int msgid;
msgid = msgget(MSGKEY,  IPC_CREAT | IPC_EXCL);//以1212為鍵值,建立一個訊息佇列,若已存在,則無法再建立

開啟訊息佇列

msgid = msgget(MSGKEY, 0);//開啟鍵值為MSGKEY的訊息佇列

傳送資訊

struct msgbuf {
	long mtype;     /* message type, must be > 0 */
	char mtext[100];  /* message data */
};//訊息佇列中傳輸的結構體型別,包括兩個部分,一個是資料型別type,一個是內容
int msgid, ret;
	struct msgbuf mbuf;
        memset(&mbuf, 0, sizeof(mbuf));
	scanf("%s", mbuf.mtext);
	mbuf.mtype = 1;//設定訊息型別為1
		
	ret = msgsnd(msgid, &mbuf, sizeof(mbuf.mtext), 0);//將mbuf結構體中的內容傳送到以msgid為描述字的訊息佇列中
	if (-1 == ret)//若傳送失敗則返回-1
	{
	    perror("msgsnd");
	    exit(1);
	}

接收訊息

ret = msgrcv(msgid, &mbuf, sizeof(mbuf.mtext), 1, 0);//接收type為1的訊息,與傳送來的資訊型別相對應
		if (-1 == ret)
		{
			perror("msgrcv");
			exit(1);
		}

訊號燈

訊號量(又名:訊號燈)與其他程序間通訊方式不大相同,主要用途是保護臨界資源(一次只允許一個程序訪問的資源)。

二值訊號燈:訊號燈的值只能取0或1,類似於互斥鎖。 但兩者有不同:

訊號燈強調共享資源,只要共享資源可用,其他程序同樣可以修改訊號燈的值;

互斥鎖更強調程序,佔用資源的程序使用完資源後,必須由程序本身來解鎖。