1 基于tmpfs的mmap系统调用过程
2 mmap的系统调用过程
3 tmpfs对mmap调用的支持
3.1 tmpfs的open调用流程
3.2 tmpfs的mmap调用过程
4 应用层如何使用mmap建立共享内存
这里假设有两个进程:进程A和进程B,他们要共享一块物理内存:region_c(通过/dev/目录的tmpfs文件: ashmem_test),再具体点,譬如进程A就是camera进程,进程B就是H264的编码线程所在的进程。则一个camera的录像过程就是:进程A获取未压缩的yuv原始视频数据,并将该视频数据数据放置在共享内存region_c区域,然后通过内存共享,进程B可以直接从共享内存region_c区域取出未压缩的原始视频数据作为该编码进程的输入,进行编码。这样就避免了大量的数据在跨进程间的拷贝,从而结余了大量的cpu时间和物理内存空间。
下面是一个如何使用共享内存的一个简单列子,需要特别注意的有以下几点:
- 关闭文件句柄,并不会清除映射
- 只有在调用munmap或是进程被终止时,才会拆除进程对应的mmap映射
- mmap系统调用后,并不会马上建立映射,而是会在随后对映射后的地址空间进行访问(读或写时)才会真正去分配物理内存,并建立相应的映射
- 对零长度的文件,可以进行mmap,但访问不成功。所以必须设置一个非零的文件长度,一般就设置为共享内存的大小。
- 映射和拆除映射都是以物理页为单位的
- #include <sys/mman.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #define SIZE_MAP 1024*4
- #define FILE_NAME "/dev/__properties5__"
- int printf_buf(unsigned char * buf, int len)
- {
- int i;
- for(i =0; i<len; i++)
- {
- printf("buf[%d]:0x%x ",i,buf[i]);
- if(!(i%4))
- printf("\n");
- }
- }
- int main(int argc, char * argv[])
- {
- int ret = 0;
- int fd = 0;
- unsigned int i =0 ;
- unsigned char *buf = NULL;
- if(!strcmp(argv[1],"a")) //进程A
- {
- fd = open(FILE_NAME,O_RDWR | O_CREAT,0777);
- if(fd > 0)
- printf("open success fd:%d\n",fd);
- else
- printf("open failed\n");
- lseek(fd,10,SEEK_SET); //注意必须要设置下文件的大小,如果文件大小是0,则不能映射
- write(fd,"",1);
- buf = (unsigned char *) mmap(NULL,SIZE_MAP,PROT_READ|PROT_WRITE, MAP_SHARED,fd,0);
- if (buf == MAP_FAILED) {
- printf("mmap failed for fd:%d\n",fd);
- close(fd);
- return -1;
- }
- printf("mmap success buf:%x \n",buf);
- printf_buf(buf, 50); //打印映射后初始化前的buf的内容
- memset(buf,0x5a,SIZE_MAP);//设置映射后的buf的内容
- close(fd); //关闭文件句柄,并不清楚映射,映射只有在munmap或进程被终止时才会被拆除
- for(i=0; i<20; i++) //设置映射后的buf的内容
- {
- buf[i] = 'a'+i;
- }
- munmap(buf,SIZE_MAP); //拆除进程A的映射
- printf("set share memory buf to 'a' for process A \n");
- // do not close fd
- }else if(!strcmp(argv[1],"b")) //进程B
- {
- fd = open(FILE_NAME,O_RDWR);
- if(fd > 0)
- printf("open success\n");
- else
- printf("open failed\n");
- buf = (unsigned char *) mmap(NULL,SIZE_MAP,PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); //将内存映射到进程B
- if (buf == MAP_FAILED) {
- printf("mmap failed for fd:%d\n",fd);
- close(fd);
- return -1;
- }
- close(fd); //关闭文件句柄,并不清除映射,映射只有在munmap或进程被终止时才会被拆除
- printf("mmap for process B success,buf:%x\n",buf);
- printf("printf share memory for process B\n");
- printf_buf(buf, 50);//打印共享内存的内容,在进程B中
- munmap(buf,SIZE_MAP);//拆除进程B的映射
- printf("completed\n");
- }else
- {
- printf("please inpu the correct parameter:\n");
- printf("shmem a \n");
- printf("or \n");
- printf("shmem b \n");
- }
- return 0;
- }
以上测试程序在X86 linux pc机上编译、测试结果如下:
rubbitxiao@szmce15:~/test/share_memory$ rm -rf shmem
rubbitxiao@szmce15:~/test/share_memory$
rubbitxiao@szmce15:~/test/share_memory$
rubbitxiao@szmce15:~/test/share_memory$ gcc -o shmem shmem.c
rubbitxiao@szmce15:~/test/share_memory$
rubbitxiao@szmce15:~/test/share_memory$
rubbitxiao@szmce15:~/test/share_memory$ ls -l
total 24
-rwxrwxr-x 1 rubbitxiao rubbitxiao 13070 Dec 8 20:51 shmem
-rwxr--r-- 1 rubbitxiao rubbitxiao 2447 Dec 8 20:50 shmem.c
-rw-rw-r-- 1 rubbitxiao rubbitxiao 3000 Dec 8 18:13 shmem.o
rubbitxiao@szmce15:~/test/share_memory$ sudo ./shmem a
open success fd:3
mmap success buf锛歝b52d000
buf[0]:0x0
buf[1]:0x0 buf[2]:0x0 buf[3]:0x0 buf[4]:0x0
buf[5]:0x0 buf[6]:0x0 buf[7]:0x0 buf[8]:0x0
buf[9]:0x0 buf[10]:0x0 buf[11]:0x0 buf[12]:0x0
buf[13]:0x0 buf[14]:0x0 buf[15]:0x0 buf[16]:0x0
buf[17]:0x0 buf[18]:0x0 buf[19]:0x0 buf[20]:0x0
buf[21]:0x0 buf[22]:0x0 buf[23]:0x0 buf[24]:0x0
buf[25]:0x0 buf[26]:0x0 buf[27]:0x0 buf[28]:0x0
buf[29]:0x0 buf[30]:0x0 buf[31]:0x0 buf[32]:0x0
buf[33]:0x0 buf[34]:0x0 buf[35]:0x0 buf[36]:0x0
buf[37]:0x0 buf[38]:0x0 buf[39]:0x0 buf[40]:0x0
buf[41]:0x0 buf[42]:0x0 buf[43]:0x0 buf[44]:0x0
buf[45]:0x0 buf[46]:0x0 buf[47]:0x0 buf[48]:0x0
buf[49]:0x0 set share memory buf to 'a' for process A
rubbitxiao@szmce15:~/test/share_memory$
rubbitxiao@szmce15:~/test/share_memory$
rubbitxiao@szmce15:~/test/share_memory$ sudo ./shmem b
open success
mmap for process B success,buf:25647000
printf share memory for process B
buf[0]:0x61
buf[1]:0x62 buf[2]:0x63 buf[3]:0x64 buf[4]:0x65
buf[5]:0x66 buf[6]:0x67 buf[7]:0x68 buf[8]:0x69
buf[9]:0x6a buf[10]:0x6b buf[11]:0x6c buf[12]:0x6d
buf[13]:0x6e buf[14]:0x6f buf[15]:0x70 buf[16]:0x71
buf[17]:0x72 buf[18]:0x73 buf[19]:0x74 buf[20]:0x5a
buf[21]:0x5a buf[22]:0x5a buf[23]:0x5a buf[24]:0x5a
buf[25]:0x5a buf[26]:0x5a buf[27]:0x5a buf[28]:0x5a
buf[29]:0x5a buf[30]:0x5a buf[31]:0x5a buf[32]:0x5a
buf[33]:0x5a buf[34]:0x5a buf[35]:0x5a buf[36]:0x5a
buf[37]:0x5a buf[38]:0x5a buf[39]:0x5a buf[40]:0x5a
buf[41]:0x5a buf[42]:0x5a buf[43]:0x5a buf[44]:0x5a
buf[45]:0x5a buf[46]:0x5a buf[47]:0x5a buf[48]:0x5a
buf[49]:0x5a completed
rubbitxiao@szmce15:~/test/share_memory$ ^C
rubbitxiao@szmce15:~/test/share_memory$