Linux系統編程—共享內存之mmap
作者:良許Linux
共享內存是通信效率最高的IPC方式,因為進程可以直接讀寫內存,而無需進行數據的拷備。但是它沒有自帶同步機制,需要配合信號量等方式來進行同步。
共享內存概念
共享內存是通信效率最高的IPC方式,因為進程可以直接讀寫內存,而無需進行數據的拷備。但是它沒有自帶同步機制,需要配合信號量等方式來進行同步。
共享內存被創建以后,同一塊物理內存被映射到了多個進程地址空間,當有一個進程修改了共享內存的數據,其余的進程均可看見所修改的內容,反之亦然。
mmap函數
函數原型:
- void mmap(void adrr, size_t length, int prot, int flags, int fd, off_t offset);
返回值:
- 成功:返回創建的映射區首地址;
- 失敗:返回MAP_FAILED
具體參數含義:
- addr:指向映射區的首地址,這是由系統內核所決定的,一般設為NULL;
- length:欲創建的映射區大小;
- prot:映射區的權限,一般有如下幾種:
- PROT_EXEC 映射區域可被執行
- PROT_READ 映射區域可被讀取
- PROT_WRITE 映射區域可被寫入
- PROT_NONE 映射區域不能存取
- flags:指映射區的標志位,MAP_FIXED與MAP_PRIVATE必須選擇一個:
- MAP_FIXED:對映射區所作的修改會反映到物理設備,但需要調用msync()或者munmap();
- MAP_PRIVATE:對映射區所作的修改不會反映到物理設備。
- fd:創建的映射區的文件描述符;
- offset:被映射文件的偏移量,一般設為0,表示從頭開始映射。
mumap函數
函數原型:
- int munmap(void *addr, size_t length);
函數作用:
如同malloc之后需要free一樣,mmap調用創建的映射區使用完畢之后,需要調用munmap去釋放。
例程
寫進程:
- #include <stdio.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- typedef struct
- {11 int id;
- char name[20];
- char gender;
- }stu;
- int main(int argc, char *argv[])
- {
- stu *p = NULL;
- int fd = 0;
- stu student = {10, "harry", 'm'};
- if (argc < 2) {
- printf("useage: ./a.out file\n");
- return -1;
- }
- fd = open(argv[1], O_RDWR | O_CREAT, 0664);
- if (fd == -1) {
- printf("ERROR: open failed!\n");
- return -1;
- }
- ftruncate(fd, sizeof(stu));
- p = mmap(NULL, sizeof(stu), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED) {
- printf("ERROR: mmap failed!\n");
- return -1;
- }
- close(fd);
- while (1) {
- memcpy(p, &student, sizeof(stu));
- student.id++;
- sleep(2);
- }
- munmap(p, sizeof(stu));
- return 0;
- }
讀進程:
- #include <stdio.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- typedef struct
- {
- int id;
- char name[20];
- char gender;
- }stu;
- int main(int argc, char *argv[])
- {
- stu *p = NULL;
- int fd = 0;
- if (argc < 2) {
- printf("useage: ./a.out file\n");
- return -1;
- }
- fd = open(argv[1], O_RDONLY);
- if (fd == -1) {
- printf("ERROR: open failed!\n");
- return -1;
- }
- p = mmap(NULL, sizeof(stu), PROT_READ, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED) {
- printf("ERROR: mmap failed!\n");
- return -1;
- }
- close(fd);
- while (1) {
- printf("id = %d, name = %s, gender = %c\n", p->id, p->name, p->gender);
- sleep(2);
- }
- munmap(p, sizeof(stu));
- return 0;
- }
本文授權轉載自公眾號「良許Linux」。良許,世界500強外企Linux開發工程師,公眾號里分享大量Linux干貨,歡迎關注!
責任編輯:趙寧寧
來源:
今日頭條