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$