一、使用管道實現進程間的通信
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)進程間的通信