1. 程式人生 > >程序的五種通訊方式

程序的五種通訊方式

一、管道

1、什麼是管道

我們把一個程序連線到另一個程序的資料流稱為一個管道。它是最古老的程序通訊形式。

2、原型(匿名管道):

#include <unistd.h>
功能:建立⼀⽆名管道
原型
int pipe(int fd[2]);
引數
fd:⽂件描述符陣列,其中fd[0]表⽰讀端, fd[1]表⽰寫端
返回值:成功返回0,失敗返回錯誤程式碼

3.管道的特點

 (1).只能用於擁有共同祖先的程序進行通訊,通常一個程序先建立管道,然後該程序呼叫fork,然後父子程序便可以一同應用此管道。

(2).管道提供流式服務。

(3).一般而言,程序退出管道釋放,管道的生命週期隨程序。

(4).一般而言,核心會對管道操作進行同步與互斥。

(5).管道是半雙工,資料只能向一個方向流動,如果要實現雙方通訊時,則需要建立兩個管道。

二、命名管道

1.建立原因:管道本只能在擁有共同祖先的程序之間通訊,若想在無關程序之間通訊,那麼則使用FIFO檔案來實現,被稱為命名管道。

2.建立命名管道

(1)命名管道可以從命令列建立

$ mkfifo filename

(2).命名管道也可以在程式中建立

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

(3)建立命名管道

int main(int argc, char *argv[])
{
 mkfifo("p2", 0644);
 return 0;
}

3.匿名管道與命名管道的區別:

  • 匿名管道由pipe建立並開啟
  • 命名管道由mkfifo建立,由open開啟
  • 兩者唯一的區別就是建立和開啟的方式不同,一旦這些完成之後,他們具有相同的語義

三、訊息佇列

1、概念

  • 訊息佇列提供了從一個程序向另一個程序傳送一塊資料的方法。
  • 每個資料塊都被認為是有一個型別,接收者程序接收的資料塊可以有不同的型別。
  • 訊息佇列的不足是訊息佇列有最大長度的限制(MSGMAX),並且還有位元組數的限制(MSGMNB),訊息佇列的總數也有限制(MSGMNI)。

2.原型:

(1).msgget()函式

功能:⽤來建立和訪問⼀個訊息佇列
原型
 int msgget(key_t key, int msgflg);
引數
 key: 某個訊息佇列的名字
 msgflg:由九個許可權標誌構成,它們的⽤法和建立⽂件時使⽤的mode模式標誌是⼀樣的
返回值:成功返回⼀個⾮負整數,即該訊息佇列的標識碼;失敗返回-1

(2)msgctl()函式

功能:訊息佇列的控制函式
原型
 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
引數
 msqid: 由msgget函式返回的訊息佇列標識碼
 cmd:是將要採取的動作,(有三個可取值)
返回值:成功返回0,失敗返回-1

(3)msgsnd()函式

功能:把⼀條訊息新增到訊息佇列中
原型
 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
引數
 msgid: 由msgget函式返回的訊息佇列標識碼
 msgp:是⼀個指標,指標指向準備傳送的訊息,
 msgsz:是msgp指向的訊息⻓度,這個⻓度不含儲存訊息型別的那個long int⻓整型
 msgflg:控制著當前訊息佇列滿或到達系統上限時將要發⽣的事情
 msgflg=IPC_NOWAIT表⽰佇列滿不等待,返回EAGAIN錯誤。
返回值:成功返回0;失敗返回-1

(4).msgrcv()函式

功能:是從⼀個訊息佇列接收訊息
原型
 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
引數
 msgid: 由msgget函式返回的訊息佇列標識碼
 msgp:是⼀個指標,指標指向準備接收的訊息,
 msgsz:是msgp指向的訊息⻓度,這個⻓度不含儲存訊息型別的那個long int⻓整型
 msgtype:它可以實現接收優先順序的簡單形式
 msgflg:控制著佇列中沒有相應型別的訊息可供接收時將要發⽣的事
返回值:成功返回實際放到接收緩衝區⾥去的字元個數,失敗返回-1

四、共享記憶體

(1).shmget函式

功能:⽤來建立共享記憶體
原型
 int shmget(key_t key, size_t size, int shmflg);
引數
 key:這個共享記憶體段名字
 size:共享記憶體⼤⼩
 shmflg:由九個許可權標誌構成,它們的⽤法和建立⽂件時使⽤的mode模式標誌是⼀樣的
返回值:成功返回⼀個⾮負整數,即該共享記憶體段的標識碼;失敗返回-1

(2).shmat函式

功能:將共享記憶體段連線到程序地址空間
原型
 void *shmat(int shmid, const void *shmaddr, int shmflg);
引數
 shmid: 共享記憶體標識
 shmaddr:指定連線的地址
 shmflg:它的兩個可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回⼀個指標,指向共享記憶體第⼀個節;失敗返回-1

(3).shmdt函式

功能:將共享記憶體段與當前程序脫離
原型
 int shmdt(const void *shmaddr);
引數
 shmaddr: 由shmat所返回的指標
返回值:成功返回0;失敗返回-1
注意:將共享記憶體段與當前程序脫離不等於刪除共享記憶體段

(4).shmctl函式

功能:⽤於控制共享記憶體
原型
 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
引數
 shmid:由shmget返回的共享記憶體標識碼
 cmd:將要採取的動作(有三個可取值)
 buf:指向⼀個儲存著共享記憶體的模式狀態和訪問許可權的資料結構
返回值:成功返回0;失敗返回-1

五、訊號量

訊號量本質上是一個計數器

訊號量結構體虛擬碼:

struct semaphore
{
 int value;
 pointer_PCB queue;
}