內存映射函數remap_pfn_range學習——示例分析(1)


作者

彭東林
QQ 405728433
 

平台

Linux-4.10.17
Qemu-2.8 + vexpress-a9
DDR:1GB
 

參考

 

概述

Linux內核提供了remap_pfn_range函數來實現將內核空間的內存映射到用戶空間:
 1 /**
 2  * remap_pfn_range - remap kernel memory to userspace
 3  * @vma: user vma to map to
 4  * @addr: target user address to start at
 5  * @pfn: physical address of kernel memory
 6  * @size: size of map area
 7  * @prot: page protection flags for this mapping
 8  *
 9  *  Note: this is only safe if the mm semaphore is held when called.
10  */
11 int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
12             unsigned long pfn, unsigned long size, pgprot_t prot);
上面的注釋對參數進行了說明。當用戶調用mmap時,驅動中的file_operations->mmap會被調用,可以在mmap中調用remap_pfn_range,它的大部分參數的值都由VMA提供。 具體可以參考LDD3的P420.
 

正文

下面結合一個簡單的例子學習一下。 在驅動中申請一個32個Page的緩沖區,這里的PAGE_SIZE是4KB,所以內核中的緩沖區大小是128KB。user_1和user_2將前64KB映射到自己的用戶空間,其中user_1向緩沖區中寫入字符串,user_2去讀取。user_3和user_4將后64KB映射到自己的用戶空間,其中user_3向緩沖區中寫入字符串,user_4讀取字符串。user_5將整個128KB映射到自己的用戶空間,然后將緩沖區清零。此外,在驅動中申請緩沖區的方式有多種,可以用kmalloc、也可以用alloc_pages,當然也可用vmalloc,下面會分別針對這三個接口實現驅動。
 
涉及到的測試程序和驅動程序可以到下面的鏈接下載:
 

一、驅動程序

下面先以kzalloc申請緩沖區的方式為例介紹,調用kmalloc申請32個頁,我們知道kzalloc返回的虛擬地址的特點是對應的物理地址也是連續的,所以在調用remap_pfn_range的時候很方便。首先在驅動init的時候申請128KB的緩沖區:
 1 static int __init remap_pfn_init(void)
 2 {
 3     int ret = 0;
 4 
 5     kbuff = kzalloc(BUF_SIZE, GFP_KERNEL);  // 這里的BUF_SIZE是128KB
 6     if (!kbuff) {
 7         ret = -ENOMEM;
 8         goto err;
 9     }
10 
11     ret = misc_register(&remap_pfn_misc);   // 注冊一個misc設備
12     if (unlikely(ret)) {
13         pr_err("failed to register misc device!\n");
14         goto err;
15     }
16 
17     return 0;
18 
19 err:
20     return ret;
21 }

第11行注冊了一個misc設備,相關信息如下:

1 static struct miscdevice remap_pfn_misc = {
2     .minor = MISC_DYNAMIC_MINOR,
3     .name = "remap_pfn",
4     .fops = &remap_pfn_fops,
5 };

這樣加載驅動后會在/dev下生成一個名為remap_pfn的節點,用戶程序可以通過這個節點跟驅動通信。其中remap_pfn_fops的定義如下:

1 static const struct file_operations remap_pfn_fops = {
2     .owner = THIS_MODULE,
3     .open = remap_pfn_open,
4     .mmap = remap_pfn_mmap,
5 };

第3行的open函數這里沒有做什么實際的工作,只是打印一些log,比如將進程的內存布局信息輸出

第4行,負責處理用戶的mmap請求,這是需要關心的。
先看一下open函數具體打印了那些內容:
 1 static int remap_pfn_open(struct inode *inode, struct file *file)
 2 {
 3     struct mm_struct *mm = current->mm;
 4 
 5     printk("client: %s (%d)\n", current->comm, current->pid);
 6     printk("code  section: [0x%lx   0x%lx]\n", mm->start_code, mm->end_code);
 7     printk("data  section: [0x%lx   0x%lx]\n", mm->start_data, mm->end_data);
 8     printk("brk   section: s: 0x%lx, c: 0x%lx\n", mm->start_brk, mm->brk);
 9     printk("mmap  section: s: 0x%lx\n", mm->mmap_base);
10     printk("stack section: s: 0x%lx\n", mm->start_stack);
11     printk("arg   section: [0x%lx   0x%lx]\n", mm->arg_start, mm->arg_end);
12     printk("env   section: [0x%lx   0x%lx]\n", mm->env_start, mm->env_end);
13 
14     return 0;
15 }
第5行將進程的名字以及pid打印出來
第6行打印進程的代碼段的范圍
第7行打印進程的data段的范圍,其中存放的是已初始化全局變量。而bss段存放的是未初始化全局變量,存放位置緊跟在data段后面,堆區之前
第8行打印進程的堆區的起始地址和當前地址
第9行打印進程的mmap區的基地址,這里的mmap區是向下增長的。具體mmap區的基地址跟系統允許的當前進程的用戶棧的大小有關,用戶棧的最大size越大,mmap區的基地址就越小。修改用戶棧的最大尺寸需要用到ulimit -s xxx命令,單位是KB,表示用戶棧的最大尺寸,用戶棧的尺寸可以上G,而內核棧卻只有區區的2個頁。
第10行打印進程的用戶棧的起始地址,向下增長
第11行和第12行的暫不關心。
 
下面是remap_pfn_mmap的實現:
 1 static int remap_pfn_mmap(struct file *file, struct vm_area_struct *vma)
 2 {
 3     unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 4     unsigned long pfn_start = (virt_to_phys(kbuff) >> PAGE_SHIFT) + vma->vm_pgoff;
 5     unsigned long virt_start = (unsigned long)kbuff + offset;
 6     unsigned long size = vma->vm_end - vma->vm_start;
 7     int ret = 0;
 8 
 9     printk("phy: 0x%lx, offset: 0x%lx, size: 0x%lx\n", pfn_start << PAGE_SHIFT, offset, size);
10 
11     ret = remap_pfn_range(vma, vma->vm_start, pfn_start, size, vma->vm_page_prot);
12     if (ret)
13         printk("%s: remap_pfn_range failed at [0x%lx  0x%lx]\n",
14             __func__, vma->vm_start, vma->vm_end);
15     else
16         printk("%s: map 0x%lx to 0x%lx, size: 0x%lx\n", __func__, virt_start,
17             vma->vm_start, size);
18 
19     return ret;
20 }

第3行的vma_pgoff表示的是該vma表示的區間在緩沖區中的偏移地址,單位是頁。這個值是用戶調用mmap時傳入的最后一個參數,不過用戶空間的offset的單位是字節(當然必須是頁對齊),進入內核后,內核會將該值右移PAGE_SHIFT(12),也就是轉換為以頁為單位。因為要在第9行打印這個編譯地址,所以這里將其再左移PAGE_SHIFT,然后賦值給offset。

第4行計算內核緩沖區中將被映射到用戶空間的地址對應的物理頁幀號。virt_to_phys接受的虛擬地址必須在低端內存范圍內,用於將虛擬地址轉換為物理地址,而vmaloc返回的虛擬地址不在低端內存范圍內,所以需要用專門的函數。
第5行計算 內核緩沖區中將被映射到用戶空間的地址對應的虛擬地址
第6行計算該vma表示的內存區間的大小
第11行調用remap_pfn_range將物理頁幀號pfn_start對應的物理內存映射到用戶空間的vm->vm_start處,映射長度為該虛擬內存區的長度。由於這里的內核緩沖區是用kzalloc分配的,保證了物理地址的連續性,所以會將物理頁幀號從pfn_start開始的(size >> PAGE_SHIFT)個連續的物理頁幀依次按序映射到用戶空間。
 
將驅動編譯成模塊后,insmod到內核。
 

二、用戶測試程序

這里的五個測試程序都很簡單,只是為了證明他們之間確實共享了同一塊內存。
user_1.c:
 1 #define PAGE_SIZE (4*1024)
 2 #define BUF_SIZE (16*PAGE_SIZE)
 3 #define OFFSET (0)
 4 
 5 int main(int argc, const char *argv[])
 6 {
 7     int fd;
 8     char *addr = NULL;
 9 
10     fd = open("/dev/remap_pfn", O_RDWR);
11     
12     addr = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, OFFSET);
13     
14     sprintf(addr, "I am %s\n", argv[0]);
15 
16     while(1)
17         sleep(1);
18     return 0;
19 }

第10和第12行,打開設備節點,然后從內核空間映射64KB的內存到用戶空間,首地址存放在addr中,由於后面既要寫入也要共享,所以設置了對應的flags。這里指定的offset是0,即映射前64KB。

第14行輸出字符串到addr指向的虛擬地址空間
 
user_2.c:
 1 #define PAGE_SIZE (4*1024)
 2 #define BUF_SIZE (16*PAGE_SIZE)
 3 #define OFFSET (0)
 4 
 5 int main(int argc, const char *argv[])
 6 {
 7     int fd;
 8     char *addr = NULL;
 9 
10     fd = open("/dev/remap_pfn", O_RDWR);
11     
12     addr = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, OFFSET);
13     
14     printf("%s", addr);
15 
16     while(1)
17         sleep(1);
18 
19     return 0;
20 }

user_2跟user_1實現一般一樣,不同之處是將addr指向的虛擬地址空間的內容打印出來。

 
user_3.c:
 1 #define PAGE_SIZE (4*1024)
 2 #define BUF_SIZE (16*PAGE_SIZE)
 3 #define OFFSET (16*PAGE_SIZE)
 4 
 5 int main(int argc, const char *argv[])
 6 {
 7     int fd;
 8     char *addr = NULL;
 9 
10     fd = open("/dev/remap_pfn", O_RDWR);
11 
12     addr = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, OFFSET);
13 
14     sprintf(addr, "I am %s\n", argv[0]);
15 
16     while(1)
17         sleep(1);
18     return 0;
19 }

第12行的OFFSET設置的是64KB,表示將內核緩沖區的后64KB映射到用戶空間

第14行,向緩沖區中輸入字符串
 
user_4.c:
 1 #define PAGE_SIZE (4*1024)
 2 #define BUF_SIZE (16*PAGE_SIZE)
 3 #define OFFSET (16*PAGE_SIZE)
 4 
 5 int main(int argc, const char *argv[])
 6 {
 7     int fd;
 8     char *addr = NULL;
 9 
10     fd = open("/dev/remap_pfn", O_RDWR);
11 
12     addr = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, OFFSET);
13 
14     printf("%s", addr);
15 
16     while(1)
17         sleep(1);
18     return 0;
19 }
第12行的OFFSET設置的是64KB,表示將內核緩沖區的后64KB映射到用戶空間
第14行,輸出緩沖區中內容
 
user_5.c:
 1 #define PAGE_SIZE (4*1024)
 2 #define BUF_SIZE (32*PAGE_SIZE)
 3 #define OFFSET (0)
 4 
 5 int main(int argc, const char *argv[])
 6 {
 7     int fd;
 8     char *addr = NULL;
 9     int *brk;
10 
11     fd = open("/dev/remap_pfn", O_RDWR);
12 
13     addr = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0);
14     memset(addr, 0x0, BUF_SIZE);
15 
16     printf("Clear Finished\n");
17 
18     while(1)
19         sleep(1);
20     return 0;
21 }
第13行,將內核緩沖區的整個128KB都映射到用戶空間
第14行,清除緩沖區中內容
 

三、測試

1、內核空間的虛擬內存布局

在內核的啟動log里可以看到內核空間的虛擬內存布局信息:
 1 [    0.000000] Virtual kernel memory layout:
 2 [    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
 3 [    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
 4 [    0.000000]     vmalloc : 0xf0800000 - 0xff800000   ( 240 MB)
 5 [    0.000000]     lowmem  : 0xc0000000 - 0xf0000000   ( 768 MB)
 6 [    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
 7 [    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
 8 [    0.000000]       .text : 0xc0008000 - 0xc0800000   (8160 kB)
 9 [    0.000000]       .init : 0xc0b00000 - 0xc0c00000   (1024 kB)
10 [    0.000000]       .data : 0xc0c00000 - 0xc0c7696c   ( 475 kB)
11 [    0.000000]        .bss : 0xc0c78000 - 0xc0cc9b8c   ( 327 kB)
用kzalloc分配的內存會落在第5行表示的虛擬內存范圍內
用vmalloc分配的內存 會落在第4行表示的虛擬內存范圍內
 

2、用戶虛擬地址空間的布局

下面是Linux系統下用戶的虛擬內存布局大致信息:
 
 
 這里需要注意的是:
  當調用malloc分配內存的時候,如果傳給malloc的參數小於128KB時,系統會在heap區分配內存,分配的方式是向高地址調整brk指針的位置。當傳給malloc的參數大於128KB時,系統會在mmap區分配,即分配一塊新的vma,其中可能會涉及到vma的合並擴展等操作。
 

3、user_1和user_2

運行user1:
[root@vexpress mnt]# ./user_1

可以看到如下內核log:

 1 [ 2494.835749] client: user_1 (870)
 2 [ 2494.835918] code  section: [0x8000   0x87f4]
 3 [ 2494.836047] data  section: [0x107f4   0x1092c]
 4 [ 2494.836165] brk   section: s: 0x11000, c: 0x11000
 5 [ 2494.836307] mmap  section: s: 0xb6f17000
 6 [ 2494.836441] stack section: s: 0xbe909e20
 7 [ 2494.836569] arg   section: [0xbe909f23   0xbe909f2c]
 8 [ 2494.836689] env   section: [0xbe909f2c   0xbe909ff3]
 9 [ 2494.836943] phy: 0x8eb60000, offset: 0x0, size: 0x10000
10 [ 2494.837176] remap_pfn_mmap: map 0xeeb60000 to 0xb6d75000, size: 0x10000

 

進程號是870,可以分別用下面的查看一下該進程的地址空間的map信息:

 1 [root@vexpress mnt]# cat /proc/870/maps 
 2 00008000-00009000 r-xp 00000000 00:12 1179664    /mnt/user_1
 3 00010000-00011000 rw-p 00000000 00:12 1179664    /mnt/user_1
 4 b6d75000-b6d85000 rw-s 00000000 00:10 8765       /dev/remap_pfn
 5 b6d85000-b6eb8000 r-xp 00000000 b3:01 143        /lib/libc-2.18.so
 6 b6eb8000-b6ebf000 ---p 00133000 b3:01 143        /lib/libc-2.18.so
 7 b6ebf000-b6ec1000 r--p 00132000 b3:01 143        /lib/libc-2.18.so
 8 b6ec1000-b6ec2000 rw-p 00134000 b3:01 143        /lib/libc-2.18.so
 9 b6ec2000-b6ec5000 rw-p 00000000 00:00 0 
10 b6ec5000-b6ee6000 r-xp 00000000 b3:01 188        /lib/libgcc_s.so.1
11 b6ee6000-b6eed000 ---p 00021000 b3:01 188        /lib/libgcc_s.so.1
12 b6eed000-b6eee000 rw-p 00020000 b3:01 188        /lib/libgcc_s.so.1
13 b6eee000-b6f0e000 r-xp 00000000 b3:01 165        /lib/ld-2.18.so
14 b6f13000-b6f15000 rw-p 00000000 00:00 0 
15 b6f15000-b6f16000 r--p 0001f000 b3:01 165        /lib/ld-2.18.so
16 b6f16000-b6f17000 rw-p 00020000 b3:01 165        /lib/ld-2.18.so
17 be8e9000-be90a000 rw-p 00000000 00:00 0          [stack]
18 bed1c000-bed1d000 r-xp 00000000 00:00 0          [sigpage]
19 bed1d000-bed1e000 r--p 00000000 00:00 0          [vvar]
20 bed1e000-bed1f000 r-xp 00000000 00:00 0          [vdso]
21 ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

上面的每一行都可以表示一個vma的映射信息,其中第4行是需要關心的:

1 b6d75000-b6d85000 rw-s 00000000 00:10 8765      /dev/remap_pfn

含義:

"b6d75000"是vma->vm_start的值,"b6d85000"是vma->vm_end的值, b6d85000減b6d75000是64KB,即給vma表示的虛擬內存區域的大小。
"rw-s"表示的是vma->vm_flags,其中's'表示share,'p'表示private
"00000000"表示偏移量,也就是vma->vm_pgoff的值
"00:10"表示該設備節點的主次設備號
"8765"表示該設備節點的inode值
"/dev/remap_pfn"表示設備節點的名字。
 
也可以用pmap查看該進程的虛擬地址空間映射信息:
 1 [root@vexpress mnt]# pmap -x 870
 2 870: {no such process} ./user_1
 3 Address      Kbytes     PSS   Dirty    Swap  Mode  Mapping
 4 00008000       4       4       0       0  r-xp  /mnt/user_1
 5 00010000       4       4       4       0  rw-p  /mnt/user_1
 6 b6d75000      64       0       0       0  rw-s  /dev/remap_pfn
 7 b6d85000    1228     424       0       0  r-xp  /lib/libc-2.18.so
 8 b6eb8000      28       0       0       0  ---p  /lib/libc-2.18.so
 9 b6ebf000       8       8       8       0  r--p  /lib/libc-2.18.so
10 b6ec1000       4       4       4       0  rw-p  /lib/libc-2.18.so
11 b6ec2000      12       8       8       0  rw-p    [ anon ]
12 b6ec5000     132      64       0       0  r-xp  /lib/libgcc_s.so.1
13 b6ee6000      28       0       0       0  ---p  /lib/libgcc_s.so.1
14 b6eed000       4       4       4       0  rw-p  /lib/libgcc_s.so.1
15 b6eee000     128     122       0       0  r-xp  /lib/ld-2.18.so
16 b6f13000       8       8       8       0  rw-p    [ anon ]
17 b6f15000       4       4       4       0  r--p  /lib/ld-2.18.so
18 b6f16000       4       4       4       0  rw-p  /lib/ld-2.18.so
19 be8e9000     132       4       4       0  rw-p  [stack]
20 bed1c000       4       0       0       0  r-xp  [sigpage]
21 bed1d000       4       0       0       0  r--p  [vvar]
22 bed1e000       4       0       0       0  r-xp  [vdso]
23 ffff0000       4       0       0       0  r-xp  [vectors]
24 --------  ------  ------  ------  ------
25 total        1808     662      48       0

 

然后運行user_2:
1 [root@vexpress mnt]# ./user_2
2 I am ./user_1

可以看到user_1寫入的信息,下面是內核log以及虛擬地址空間映射信息:

 1 [ 2545.832903] client: user_2 (873)
 2 [ 2545.833087] code  section: [0x8000   0x87e0]
 3 [ 2545.833178] data  section: [0x107e0   0x10918]
 4 [ 2545.833262] brk   section: s: 0x11000, c: 0x11000
 5 [ 2545.833346] mmap  section: s: 0xb6fb5000
 6 [ 2545.833423] stack section: s: 0xbea0ee20
 7 [ 2545.833499] arg   section: [0xbea0ef23   0xbea0ef2c]
 8 [ 2545.833590] env   section: [0xbea0ef2c   0xbea0eff3]
 9 [ 2545.833761] phy: 0x8eb60000, offset: 0x0, size: 0x10000
10 [ 2545.833900] remap_pfn_mmap: map 0xeeb60000 to 0xb6e13000, size: 0x10000
11 
12 [root@vexpress mnt]# cat /proc/873/maps 
13 00008000-00009000 r-xp 00000000 00:12 1179665    /mnt/user_2
14 00010000-00011000 rw-p 00000000 00:12 1179665    /mnt/user_2
15 b6e13000-b6e23000 rw-s 00000000 00:10 8765       /dev/remap_pfn
16 b6e23000-b6f56000 r-xp 00000000 b3:01 143        /lib/libc-2.18.so
17 b6f56000-b6f5d000 ---p 00133000 b3:01 143        /lib/libc-2.18.so
18 b6f5d000-b6f5f000 r--p 00132000 b3:01 143        /lib/libc-2.18.so
19 b6f5f000-b6f60000 rw-p 00134000 b3:01 143        /lib/libc-2.18.so
20 b6f60000-b6f63000 rw-p 00000000 00:00 0 
21 b6f63000-b6f84000 r-xp 00000000 b3:01 188        /lib/libgcc_s.so.1
22 b6f84000-b6f8b000 ---p 00021000 b3:01 188        /lib/libgcc_s.so.1
23 b6f8b000-b6f8c000 rw-p 00020000 b3:01 188        /lib/libgcc_s.so.1
24 b6f8c000-b6fac000 r-xp 00000000 b3:01 165        /lib/ld-2.18.so
25 b6fb0000-b6fb3000 rw-p 00000000 00:00 0 
26 b6fb3000-b6fb4000 r--p 0001f000 b3:01 165        /lib/ld-2.18.so
27 b6fb4000-b6fb5000 rw-p 00020000 b3:01 165        /lib/ld-2.18.so
28 be9ee000-bea0f000 rw-p 00000000 00:00 0          [stack]
29 beedf000-beee0000 r-xp 00000000 00:00 0          [sigpage]
30 beee0000-beee1000 r--p 00000000 00:00 0          [vvar]
31 beee1000-beee2000 r-xp 00000000 00:00 0          [vdso]
32 ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

上面的的log信息可以查看: https://github.com/pengdonglin137/remap_pfn_demo/blob/master/log/user2

 
根據上面的空間映射信息可以得到下面的示意圖:
 

4、user_3和user_4

相關的log信息可以查看:
 
下面是運行user3的log和映射信息:
 1 [ 4938.000918] client: user_3 (884)
 2 [ 4938.001117] code  section: [0x8000   0x87f4]
 3 [ 4938.001205] data  section: [0x107f4   0x1092c]
 4 [ 4938.001281] brk   section: s: 0x11000, c: 0x11000
 5 [ 4938.001410] mmap  section: s: 0xb6ff1000
 6 [ 4938.001485] stack section: s: 0xbea10e20
 7 [ 4938.001549] arg   section: [0xbea10f23   0xbea10f2c]
 8 [ 4938.001606] env   section: [0xbea10f2c   0xbea10ff3]
 9 [ 4938.001793] phy: 0x8eb70000, offset: 0x10000, size: 0x10000
10 [ 4938.001996] remap_pfn_mmap: map 0xeeb70000 to 0xb6e4f000, size: 0x10000
11 
12 [root@vexpress mnt]# 
13 [root@vexpress mnt]# cat /proc/884/maps 
14 00008000-00009000 r-xp 00000000 00:12 1179666    /mnt/user_3
15 00010000-00011000 rw-p 00000000 00:12 1179666    /mnt/user_3
16 b6e4f000-b6e5f000 rw-s 00010000 00:10 8765       /dev/remap_pfn
17 b6e5f000-b6f92000 r-xp 00000000 b3:01 143        /lib/libc-2.18.so
18 b6f92000-b6f99000 ---p 00133000 b3:01 143        /lib/libc-2.18.so
19 b6f99000-b6f9b000 r--p 00132000 b3:01 143        /lib/libc-2.18.so
20 b6f9b000-b6f9c000 rw-p 00134000 b3:01 143        /lib/libc-2.18.so
21 b6f9c000-b6f9f000 rw-p 00000000 00:00 0 
22 b6f9f000-b6fc0000 r-xp 00000000 b3:01 188        /lib/libgcc_s.so.1
23 b6fc0000-b6fc7000 ---p 00021000 b3:01 188        /lib/libgcc_s.so.1
24 b6fc7000-b6fc8000 rw-p 00020000 b3:01 188        /lib/libgcc_s.so.1
25 b6fc8000-b6fe8000 r-xp 00000000 b3:01 165        /lib/ld-2.18.so
26 b6fed000-b6fef000 rw-p 00000000 00:00 0 
27 b6fef000-b6ff0000 r--p 0001f000 b3:01 165        /lib/ld-2.18.so
28 b6ff0000-b6ff1000 rw-p 00020000 b3:01 165        /lib/ld-2.18.so
29 be9f0000-bea11000 rw-p 00000000 00:00 0          [stack]
30 bebe9000-bebea000 r-xp 00000000 00:00 0          [sigpage]
31 bebea000-bebeb000 r--p 00000000 00:00 0          [vvar]
32 bebeb000-bebec000 r-xp 00000000 00:00 0          [vdso]
33 ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

需要關注的是第16行,其中的"00010000"表示offset,大小是64KB,也就是vma->vm_pgoff的值。

下面是user_3和user_4的共享內存的示意圖:

5、user_5

user_5負責將128KB的內核緩沖區映射到自己的用戶空間,並清除其中的內容。
下面是映射示意圖:
 
 
 
 
未完待續...
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM