IPC三種通信機制是指:信號量、共享內存、消息隊列,
信號量:通過操作系統中的PV操作來實現;
共享內存:申請一塊內存,進程A往共享內存中寫,其他的進程就可以通過讀出共享內存中的內容來獲取進程A所傳送的信息;
消息隊列:創建一個消息隊列,進程A往隊列里面寫,那么進程B通過讀隊列中的容來獲取進程A傳送的信息。
mmap可以把磁盤文件的一部分直接映射到內存,這樣文件中的位置直接就有對應的內存地址,對文件的讀寫可以直接用指針來操做而不需要read/write函數。
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length);
如果addr參數為NULL,內核會自己在進程地址空間中選擇合適的地址建立映射。如果addr不是NULL,則給內核一個提示,應該從什么地址開始映射,內核會選擇addr之上的某個合適的地址開始映射。建立映射后,真正的映射首地址通過返回值可以得到。len參數是需要映射的那一部分文件的長度。off參數是從文件的什么位置開始映射,必須是頁大小的整數倍(在32位體系統結構上通常是4K)。filedes是代表該文件的描述符。
prot參數有四種取值:
1)PROT_EXEC 表示映射的這一段可執行,例如映射共享庫
2)PROT_READ 表示映射的這一段可讀
3)PROT_WRITE 表示映射的這一段可寫
4) PROT_NONE 表示映射的這一段不可訪問
flag參數有很多種取值,這里只講兩種常用的,其它取值可查看mmap(2)
- MAP_SHARED 多個進程對同一個文件的映射是共享的,一個進程對映射的內存做了修改,另一個進程也會看到這種變化。
- MAP_PRIVATE 多個進程對同一個文件的映射不是共享的,一個進程對映射的內存做了修改,另一個進程並不會看到這種變化,也不會真的寫到文件中去。
* 如果mmap成功則返回映射首地址,如果出錯則返回常數MAP_FAILED。當進程終止時,該進程的映射內存會自動解除,也可以調用munmap解除映射。munmap成功返回0,出錯返回-1。
/* 運行前准備 */ book@ubuntu:~$ vi hello book@ubuntu:~$ cat hello helloworld book@ubuntu:~$ od -tx1 -tc hello 0000000 68 65 6c 6c 6f 77 6f 72 6c 64 0a h e l l o w o r l d \n 0000013
#include <stdio.h>
#include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <sys/mman.h> int main(void) { int fd, *p, len; fd = open("hello",O_RDWR); if(fd < 0) { perror("open"); exit(1); } //獲取文件長度 len = lseek(fd, 0, SEEK_END); //建立映射 p = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if(p == MAP_FAILED) {//如果失敗,記住這種檢測方式 perror("mmap"); exit(1); } //即使關閉文件也不會釋放映射 close(fd); //由於是共享映射,所以映射源也會被修改 p[0] = 0x30313233; munmap(p, len); return 0; } /* 運行后結果(小端存儲的原因) */ book@ubuntu:~$ cat hello 3210oworld book@ubuntu:~$ od -tx1 -tc hello 0000000 33 32 31 30 6f 77 6f 72 6c 64 0a 3 2 1 0 o w o r l d \n 0000013
利用內存映射的特性,也可以用於進程間的通信,但是要注意的是: 1、用於進程間通信時,一般設計成結構體,來傳輸通信的數據 2、進程間通信的文件,應該設計成臨時文件(即創建文件,使用文件,刪除文件) 3、 當報總線錯誤時,優先查看共享文件是否有存儲空間