day_13_管道、共享內存、消息隊列

一、使用管道實現進程間的通信

1.1 基本概念

  管道本質上還是以文件作爲媒介,只是該文件比較特殊,叫做管道文件而已;
  管道主要分爲兩大類:有名管道 和 無名管道;
    有名管道 - - - - - - 可以用於任意兩個進程間的通信
    無名管道 - - - - - - 主要用於父子進程之間的通信

1.2 使用有名管道實現進程間的通信

  $ mkfifo xxx.pipe:表示創建管道文件
如:
  $ touch a.txt      => 創建普通文件a.txt,ls -l該文件的類型是-
  $ echo hello > a.txt  => 表示寫入hello到文件a.txt中,可以寫入,文件大小改變
  $ cat a.txt        => 表示查看文件a.txt中的內容,可以看到寫入的hello
  $ mkfifo a.pipe     => 創建管道文件a.pipe,ls -l該文件的類型是p
  $ echo hello > a.pipe =>表示寫入hello到文件a.pipe中,不可以寫入,大小不變
另起一個終端,執行命令:
  $ cat a.pipe      => 表示讀取文件a.pipe中的內容,可以看到hello
               => 但是文件本身的大小還是不變;

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);  //mode_t = unsigned int;
功能:
主要用於創建參數指定的有名管道文件;
參數:
第一個參數:字符串形式的路徑名;
第二個參數:具體的權限信息,如:0664;

1.3 使用無名管道實現進程間的通信

#include <unistd.h>
int pipe(int pipefd[2]);
功能:
主要用於創建一個無名管道,是一個單向的數據通道,可以實現兩個進程之間的通信;
通過參數數組可以返回兩個文件描述符,其中pipefd[0]代表管道的讀端,pipefd[1]代表管道的寫端;
注意:
管道文件的特殊性就在於僅僅作爲兩個進程間通信的媒介,但是該文件本身並不會存儲任何數據內容;

二、使用共享內存實現進程間的通信

2.1 基本概念

  共享內存本質上就是一塊由系統內核維護的內存空間,該內存空間被共享在兩個進程之間,從而通過讀寫實現通信;

2.2 通信模型

 (1)獲取key值,使用ftok();
 (2)創建 / 獲取共享內存,使用shmget();
 (3)掛接共享內存,使用shmat();
 (4)訪問共享內存;
 (5)脫接共享內存,使用shmdt();
 (6)如果不再使用,則刪除共享內存,使用shmctl();

2.3 相關函數的解析

(1)ftok()

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);  //key_t = int;
功能:
主要用於根據路徑名和項目的編號來生成key值;
參數:
第一個參數:字符串形式的路徑名;(要求文件必須存在,並且可以訪問)
第二個參數:項目的編號;(要求必須是非0,取低八位二進制位)
返回值:
success —- key_t類型的key值,error —- -1;
注意:
使用相同的文件路徑和相同的項目編號時,生成的key值也相同;

(2)shmget()

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:
主要用於創建 / 獲取一個共享內存段;
參數:
第一個參數:key值,ftok()的返回值;
第二個參數:共享內存的大小;
  0 - - - - - - - - - - - - - - - 獲取已經存在的共享內存
第三個參數:具體的操作標誌;
  IPC_CREAT - - - - - - 若存在則創建,存在則打開
  IPC_EXCL - - - - - - - 與IPC_CREAT搭配使用,若存在則創建失敗
  0 - - - - - - - - - - - - - - -獲取已經存在的共享內存
返回值:
success —- 共享內存的ID,error —- -1;
注意:
當創建新的共享內存時,需要在第三個參數中通過按位或的方式來指定權限信息,如:0664;

(3)shmat()

#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
主要用於掛接共享內存到當前進程的地址空間中;
參數:
第一個參數:共享內存的ID,shmget()的返回值;
第二個參數:共享內存的起始地址,給NULL由系統選擇;
第三個參數:具體的操作標誌,默認給0即可;
返回值:
success —- 共享內存段的掛接地址,error —- (void*)-1;

(4)shmdt()

#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
功能:
主要用於脫接參數指定的掛接地址,參數一般傳遞shmat()的返回值;

(5)shmctl()

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
主要用於對指定的共享內存執行指定的操作;
參數:
第一個參數:共享內存的ID,shmget()的返回值;
第二個參數:具體的操作命令;
  IPC_RMID - - - - - 刪除共享內存,此時第三個參數給NULL即可
第三個參數:結構體指針

2.4 常見的基本命令

  $ ipcs -m - - - - - - - - - - - - - - - - - 表示查看系統中已經存在的共享內存
  $ ipcrm -m 共享內存的ID - - - – 表示刪除指定的共享內存


三、使用消息隊列實現進程間的通信

3.1 基本概念

  一般來說,首先將傳遞的數據打包成消息,然後使用兩個進程分別發送消息到消息隊列中 / 接收消息隊列中的消息,從而實現進程間的通信;

3.2 通信模型

 (1)獲取key值,使用ftok();
 (2)創建 / 獲取消息隊列,使用msgget();
 (3)發送消息到消息隊列 / 接收消息隊列中的消息,使用msgsnd() / msgrcv();
 (4)如果不再使用,則刪除消息隊列,使用msgctl();

3.3 相關函數的解析

(1)msgget()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:
主要用於創建 / 獲取一個消息隊列;
參數:
第一個參數:key值,ftok()的返回值;
第二個參數:具體的操作標誌;
  IPC_CREAT - - - - - - 若不存在則創建,存在則打開;
  IPC_EXCL - - - - - - - 與IPC_CREAT搭配使用,若存在則創建失敗
  0 - - - - - - - - - - - - - – 獲取已經存在的消息隊列
返回值:
success —- 消息隊列的ID,error —- -1;
注意:
當創建新的消息隊列時,在第二個參數中需要通過按位或的方式來指定權限信息,如:0664;

(2)msgsnd()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:
主要用於將指定的消息發送到指定的消息隊列中;
參數:
第一個參數:消息隊列的ID,msgget()的返回值;
第二個參數:消息的首地址,消息的一般格式如下:
struct msgbuf
{
    long mtype;       /* 消息的類型,必須大於0 */
    char mtext[1];    /* 消息的內容,可以是其他類型 */
};

   第三個參數:消息的大小;(用於指定消息內容的大小,不包括消息的類型)
   第四個參數:發送的標誌,默認給0即可;

(3)msgrcv()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
/* ssize_t = long int; size_t = long unsigned int */
功能:
主要用於從指定的消息隊列中接收指定的消息;
參數:
第一個參數:消息隊列的ID,msgget()的返回值;
第二個參數:存放信息的首地址;
第三個參數:消息的大小;(用於指定消息內容的大小,不包括消息的類型)
第四個參數:消息的類型;
  0 - - - - - - - 表示始終讀取消息隊列中的第一個消息
  >0 - - - - - - 表示始終讀取消息隊列中第一個類型爲msgtyp的消息
  <0 - - - - - - 表示讀取消息隊列中小於等於msgtyp絕對值的消息,其中最小的類型優先讀取
第五個參數:具體的接收方式,默認給0即可;
返回值:
success —- 實際讀取的字節數,error —- -1;

(4)msgctl()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
主要用於刪除消息隊列;
參數:
第一個參數:消息隊列的ID;
第二個參數:具體的操作命令;
  IPC_RMID - - - - - - - - 刪除消息隊列,此時第三個參數給NULL即可
第三個參數:結構體指針;

3.4 常見的基本命令

  $ ipcs -q - - - - - - - - - - - - - - - - - 表示查看系統中已經存在的消息隊列
  $ ipcrm -q 消息隊列的ID - - - – 表示刪除指定的消息隊列

明日預報:
(1)進程間的通信
發佈了50 篇原創文章 · 獲贊 48 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章