分类: LINUX
- if (file) {
- 989 switch (flags & MAP_TYPE) {
- 990 case MAP_SHARED:
- 991 if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE))
- 992 return -EACCES;
- 993
- 994 /*
- 995 * Make sure we don't allow writing to an append-only
- 996 * file..
- 997 */
- 998 if (IS_APPEND(inode) && (file->f_mode & FMODE_WRITE))
- 999 return -EACCES;
- 1000
- 1001 /*
- 1002 * Make sure there are no mandatory locks on the file.
- 1003 */
- 1004 if (locks_verify_locked(inode))
- 1005 return -EAGAIN;
- 1006
- 1007 vm_flags |= VM_SHARED | VM_MAYSHARE;
- 1008 if (!(file->f_mode & FMODE_WRITE))
- 1009 vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
- 1010
- 1011 /* fall through */
- 1012 case MAP_PRIVATE:
- 1013 if (!(file->f_mode & FMODE_READ))
- 1014 return -EACCES;
- 1015 break;
- 1016
- 1017 default:
- 1018 return -EINVAL;
- 1019 }
- 1020 } else {
- 1021 switch (flags & MAP_TYPE) {
- 1022 case MAP_SHARED:
- 1023 vm_flags |= VM_SHARED | VM_MAYSHARE;
- 1024 break;
- 1025 case MAP_PRIVATE:
- 1026 /*
- 1027 * Set pgoff according to addr for anon_vma.
- 1028 */
- 1029 pgoff = addr >> PAGE_SHIFT;
- 1030 break;
- 1031 default:
- 1032 return -EINVAL;
- 1033 }
- 1034 }
default:
return -EINVAL;
以下四种情况调用这个函数 所得到的结果:
1)找一个低地址区间,此区间还没有被映射。
unsigned long addr1 = do_mmap_pgoff(NULL,0x1000,0x7000, PROT_WRITE,MAP_FIXED|MAP_PRIVATE,0);
模块代码编译执行后,得到的dmesg输出结果为
这个函数被调用前的线性区情况(作为对比):
vm_area_struct:280000 - 281000
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:98c1000 - 98e2000
vm_area_struct:b7f57000 - b7f59000
vm_area_struct:bf90f000 - bf924000
VMA nr:14
第一次调用的结果:
vm_area_struct:1000 - 8000
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:e58000 - e59000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:9509000 - 952a000
vm_area_struct:b7f9b000 - b7f9d000
vm_area_struct:bfdea000 - bfdff000
VMA nr:15
OK....没有发生任何合并和删除
简单的示意图:(不考虑其余已经存在的线性区,在我们的例子中是已经存在了14个VMA)
2)在映射的区间上执行do_mmap_pgoff函数但是新区间的标志以原来的区间不同,不能进行合并
unsigned long addr1 = do_mmap_pgoff(NULL,0x1000,0x7000, PROT_WRITE,MAP_FIXED|MAP_SHARED,0);
unsigned long addr = do_mmap_pgoff(NULL,0x8000,0x2000, PROT_WRITE,MAP_FIXED|MAP_PRIVATE,0);
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:657000 - 658000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:898a000 - 89ab000
vm_area_struct:b7f55000 - b7f57000
vm_area_struct:bfa76000 - bfa8b000
VMA nr:14
vm_area_struct:1000 - 8000
vm_area_struct:8000 - a000
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:657000 - 658000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:898a000 - 89ab000
vm_area_struct:b7f55000 - b7f57000
vm_area_struct:bfa76000 - bfa8b000
VMA nr:16
3)新区间的标志以新区间之前的区间标志相同,能进行合并
unsigned long addr1 = do_mmap_pgoff(NULL,0x1000,0x7000, PROT_WRITE,MAP_FIXED|MAP_PRIVATE,0);
unsigned long addr = do_mmap_pgoff(NULL,0x8000,0x2000, PROT_WRITE,MAP_FIXED|MAP_PRIVATE,0);
这种情况有一点需要注意:匿名共享的线性区(MAP_SHARED)是不允许合并的;
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:b24000 - b25000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:9537000 - 9558000
vm_area_struct:b7fd0000 - b7fd2000
vm_area_struct:bfab7000 - bfacc000
VMA nr:14
vm_area_struct:1000 - a000
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:b24000 - b25000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:9537000 - 9558000
vm_area_struct:b7fd0000 - b7fd2000
vm_area_struct:bfab7000 - bfacc000
VMA nr:15
4)新的线性区在一个已有的线性区中间 切标志与前后的线性区都不同。不能进行合并。
unsigned long addr1 = do_mmap_pgoff(NULL,0x1000,0x9000, PROT_WRITE,MAP_FIXED|MAP_PRIVATE,0);
unsigned long addr = do_mmap_pgoff(NULL,0x2000,0x1000, PROT_WRITE,MAP_FIXED|MAP_SHARED,0);
vm_area_struct:435000 - 436000
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:86bb000 - 86dc000
vm_area_struct:b7f5c000 - b7f5e000
vm_area_struct:bf822000 - bf837000
VMA nr:14
vm_area_struct:1000 - 2000
vm_area_struct:2000 - 3000
vm_area_struct:3000 - a000
vm_area_struct:435000 - 436000
vm_area_struct:469000 - 483000
vm_area_struct:483000 - 484000
vm_area_struct:484000 - 485000
vm_area_struct:487000 - 5c6000
vm_area_struct:5c6000 - 5c7000
vm_area_struct:5c7000 - 5c9000
vm_area_struct:5c9000 - 5ca000
vm_area_struct:5ca000 - 5cd000
vm_area_struct:8048000 - 8049000
vm_area_struct:8049000 - 804b000
vm_area_struct:86bb000 - 86dc000
vm_area_struct:b7f5c000 - b7f5e000
vm_area_struct:bf822000 - bf837000
VMA nr:17