【Linux 應用編程】進程管理 - 進程間通訊IPC之共享內存 mmap

IPC(InterProcess Communication,進程間通訊)是進程中的重要概念。Linux 進程之間經常使用的通訊方式有:web

  • 文件:簡單,低效,須要代碼控制同步
  • 管道:使用簡單,默認阻塞
    • 匿名管道 pipe:只存在於內核緩衝區,只能用於有血緣關係的進程
    • 有名管道 FIFO:在文件系統中存在,可用於無血緣關係的進程
  • 信號量:使用複雜,但開銷小,操做系統自己支持信號量
  • 內存映射區 mmap:進程有無血緣關係均可以
  • 本地套接字 socket:穩定可靠

共享內存

經過共享內存,兩個不相干的進程可使用同一段邏輯內存。這塊內存一般也是同一段物理內存。每一個進程都把這段共享內存鏈接到本身的地址空間中,直接訪問。socket

共享內存是進程間傳遞數據的經常使用方式,很是高效。svg

共享內存的使用

POSIX 共享內存區的使用包含四個步驟:函數

  • 調用 shm_open 建立一個新的共享內存區對象(或打開一個以存在的共享內存區對象)
  • 調用 mmap 把這個共享內存區映射到調用進程的地址空間
  • 調用 munmap() 取消共享內存映射
  • 調用 shm_unlink()函數刪除共享內存段

在編譯 POSIX 共享內存應用程序時須要加上 -lrt 參數。spa

shm_open 函數

shm_open() 函數用來打開或者建立一個共享內存區,兩個進程能夠經過給 shm_open() 函數傳遞相同的名字以達到操做同一共享內存的目的。操作系統

新建的共享內存區大小默認爲 0,須要使用 ftruncate 函數設置大小才能使用。code

函數原型:xml

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
int shm_open(const char *name, int oflag, mode_t mode);

返回值:
成功返回建立或打開的共享內存描述符(與文件描述符相同做用),失敗返回-1。對象

參數:token

  • name:建立的共享內存的名稱,其它進程能夠根據這個名稱來打開共享內存
  • oflag:如下值的或值:
    • O_RDONLY:共享內存以只讀方式打開;
    • O_RDWR:共享內存以可讀寫方式打開;
    • O_CREAT:共享內存不存在才建立;
    • O_EXCL:若是指定了 O_CREAT,但共享內存已經存在時返回錯誤;
    • O_TRUNC:若是共享內存已存在則將大小設置爲 0;
  • 參數 mode 只有指定 O_CREAT 纔有效指出,指出共享內存的權限,與 open()函數
    相似。

ftruncate 函數

新建的共享內存默認大小爲 0,須要設置共享內存大小。ftruncate()函數可用來調整文件或者共享內存的大小。

函數原型:

#include <unistd.h>
#include <sys/types.h>
int ftruncate(int fd, off_t length);

函數成功返回 0,失敗返回-1。
參數:

  • fd:須要調整的共享內存或者文件
  • length:大小

mmap 函數

共享內存建立或打開後,是不能在進程內直接使用的。須要先映射到當前進程的地址空間。

函數原型:

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

參數:

  • addr:指向映射存儲區的起始地址,一般將其設置爲 NULL,這表示由系統選擇該
    映射區的起始地址;
  • len:映射的字節數;
  • prot:對映射存儲區的保護要求,對指定映射存儲區的保護要求不能超過文件 open
    模式訪問權限。它能夠爲如下值的或值:
    • PROT_READ:映射區可讀);
    • PROT_WRITE:映射區可寫;
    • PROT_EXEC:映射區可執行;
    • PROT_NONE:映射區不可訪問。
  • flag:映射標誌位,可爲如下值的或值:
    • MAP_FIXED:返回值必須等於 addr。由於這不利於可移植性,因此不鼓勵使用此標誌;
    • MAP_SHARED:多個進程對同一個文件的映射是共享的,一個進程對映射的
      內存作了修改,另外一個進程也會看到這種變化;
      MAP_PRIVATE:多個進程對同一個文件的映射不是共享的,一個進程對映射
      的內存作了修改,另外一個進程並不會看到這種變化。
  • fd:要被映射的文件描述符或者共享內存描述符;
  • offset:要映射字節在文件中的起始偏移量。

munmap 函數

函數原型:

#include <sys/mman.h>
int munmap(void *addr, size_t length);

函數成功返回 0,不然返回-1;
參數:

  • addr 爲 mmap()函數返回的地址
  • length 是映射的字節數。取消映射後再對映射地址訪問會致使調用進程收到 SIGSEGV 信號。

shm_unlink 函數

函數原型:

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
int shm_unlink(const char *name);

函數成功返回 0,不然返回-1。

示例

兩個沒有血緣關係的進程,也可使用共享內存進行進程間通訊:

相關文章
相關標籤/搜索