Linux系統(tǒng)編程—共享內(nèi)存之mmap
共享內(nèi)存概念
共享內(nèi)存是通信效率最高的IPC方式,因?yàn)檫M(jìn)程可以直接讀寫內(nèi)存,而無需進(jìn)行數(shù)據(jù)的拷備。但是它沒有自帶同步機(jī)制,需要配合信號(hào)量等方式來進(jìn)行同步。
共享內(nèi)存被創(chuàng)建以后,同一塊物理內(nèi)存被映射到了多個(gè)進(jìn)程地址空間,當(dāng)有一個(gè)進(jìn)程修改了共享內(nèi)存的數(shù)據(jù),其余的進(jìn)程均可看見所修改的內(nèi)容,反之亦然。
mmap函數(shù)
函數(shù)原型:
- void mmap(void adrr, size_t length, int prot, int flags, int fd, off_t offset);
返回值:
- 成功:返回創(chuàng)建的映射區(qū)首地址;
- 失?。悍祷豈AP_FAILED
具體參數(shù)含義:
- addr:指向映射區(qū)的首地址,這是由系統(tǒng)內(nèi)核所決定的,一般設(shè)為NULL;
- length:欲創(chuàng)建的映射區(qū)大小;
- prot:映射區(qū)的權(quán)限,一般有如下幾種:
- PROT_EXEC 映射區(qū)域可被執(zhí)行
- PROT_READ 映射區(qū)域可被讀取
- PROT_WRITE 映射區(qū)域可被寫入
- PROT_NONE 映射區(qū)域不能存取
- flags:指映射區(qū)的標(biāo)志位,MAP_FIXED與MAP_PRIVATE必須選擇一個(gè):
- MAP_FIXED:對(duì)映射區(qū)所作的修改會(huì)反映到物理設(shè)備,但需要調(diào)用msync()或者munmap();
- MAP_PRIVATE:對(duì)映射區(qū)所作的修改不會(huì)反映到物理設(shè)備。
- fd:創(chuàng)建的映射區(qū)的文件描述符;
- offset:被映射文件的偏移量,一般設(shè)為0,表示從頭開始映射。
mumap函數(shù)
函數(shù)原型:
- int munmap(void *addr, size_t length);
函數(shù)作用:
如同malloc之后需要free一樣,mmap調(diào)用創(chuàng)建的映射區(qū)使用完畢之后,需要調(diào)用munmap去釋放。
例程
寫進(jìn)程:
- #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;
- }
讀進(jìn)程:
- #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;
- }
本文授權(quán)轉(zhuǎn)載自公眾號(hào)「良許Linux」。良許,世界500強(qiáng)外企Linux開發(fā)工程師,公眾號(hào)里分享大量Linux干貨,歡迎關(guān)注!