OK6410A 开发板 (八) 104 linux-5.11 OK6410A mmap四种用途参数及扩展

  • mmap 的用途
共享文件映射
	一个应用场景就是两个进程共同读写一个文本文件,比如你用vim编辑保存后,再用cat命令查看
私有文件映射
	最典型的应用就是进程对动态链接库(比如libc.so)的使用
共享匿名映射
	一个典型应用是作为进程间通信机制的POSIX共享内存
私有匿名映射
	用来实现glibc中的malloc

  • mmap 的函数及参数的排列组合
 #include <sys/mman.h>

 void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

prot :
	PROT_READ
	PROT_WRITE
	PROT_NONE
	PROT_EXEC
flags:
	MAP_SHARED
	MAP_PRIVATE
	MAP_ANON/MAP_ANONYMOUS
fd:
	-1
	0/1/2
	3/4/5...
---------------------------------
共享文件映射
	fd 		: 3/4/5...
	flags	: MAP_SHARED
私有文件映射
	id 		: 3/4/5...
	flags   : MAP_PRIVATE
共享匿名映射
	id 		: -1
	flags 	: MAP_SHARED|MAP_ANONYMOUS
私有匿名映射
	id 		: -1
	flags 	:MAP_PRIVATE|MAP_ANONYMOUS

mmap 的典型应用

/dev/shm/xxx
  • /dev/shm/xxx 进程通信之共享内存
共享内存实现方案有多种,posix共享内存是其中的一种
posix共享内存是一种通信方式,其基于 mmap 和 (文件系统shmem)

内存文件系统shmem 	提供 fd 和 shmemfs 所有文件共享的 file_operations // shmemfs 被 挂载到 /dev/shm
						shmem_file_operations 提供 generic_file_mmap 或者 shmem_mmap
						底层用到了 shmem_vm_ops , shmem_vm_ops 重定位 到 shmem_vm_ops 或者 generic_file_vm_ops
mmap 				提供 访问 fd 对应的 内存 的 技术  // 参数填充 符合 "共享文件映射"

/dev/xxx
  • /dev/zero
共享匿名映射 
	在内核中走到了
	mmap_region-> mm/mmap.c(1844)shmem_zero_setup,
	其实用到了 "/dev/zero" 文件
	往下用到了 基于 tmpfs 的 shmem_vm_ops , shmem_vm_ops 重定位 到 shmem_vm_ops 或者 generic_file_vm_ops
共享文件映射 // 当 fd 为 "/dev/zero" 时
	在内核中走到了
	mmap_region-> mm/mmap.c(1807)call_mmap(即mmap_zero)->shmem_zero_setup
	往下用到了 基于 tmpfs 的 shmem_vm_ops , shmem_vm_ops 重定位 到 shmem_vm_ops 或者 generic_file_vm_ops


/dev/zero 对应  的 file_operations 提供  zero_fops 的 mmap_zero

  • dev/fb0
/dev/fb0 	提供了 句柄 和 该文件独有的file_operations // 类似 /dev/zero
				fb_fops 提供 fb_mmap
				符合 https://blog.csdn.net/u011011827/article/details/117371188 中 "分体流程 针对文件xx映射" 的 第一种情况
				// 在file->f_op->mmap (fb_mmap )前已经分配了物理内存,file->f_op->mmap (fb_mmap ) 只做了映射
mmap 		提供了 访问 fd 对应的 内存 的 技术 		 // 参数填充 符合 "共享文件映射"
  • dev/mem
[DEVMEM_MINOR] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
mem_fops 提供 mmap_mem

符合 https://blog.csdn.net/u011011827/article/details/117371188 中 "分体流程 针对文件xx映射" 的 第一种情况
	// 在file->f_op->mmap (mmap_mem)前已经分配了物理内存,file->f_op->mmap (mmap_mem) 只做了映射

  • /dev/kmem
[2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET },
.mmap       = mmap_kmem,

符合 https://blog.csdn.net/u011011827/article/details/117371188 中 "分体流程 针对文件xx映射" 的 第一种情况
	// 在file->f_op->mmap (mmap_kmem)前已经分配了物理内存,file->f_op->mmap (mmap_kmem) 只做了映射
  • 其他 file_operations mmap 成员为 NULL 的 /dev/文件
//  dev/tty
tty_init
	cdev_init(&tty_cdev, &tty_fops);
	cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1);
	register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty");
	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");

//  dev/console
tty_init
	cdev_init(&console_cdev, &console_fops);
	cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1);
	register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console")
	device_create_with_groups(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, cons_dev_groups, "console");
	console_fops  的 mmap 成员 为 NULL
//  dev/null
[3] = { "null", 0666, &null_fops, 0 },
.mmap       = NULL,
//  dev/port
[4] = { "port", 0, &port_fops, 0 }
.mmap       = NULL,
//  dev/full
[7] = { "full", 0666, &full_fops, 0 },
.mmap       = NULL,
//  dev/random
[8] = { "random", 0666, &random_fops, 0 },
.mmap       = NULL,
//  dev/urandom
[9] = { "urandom", 0666, &urandom_fops, 0 },
.mmap       = NULL,
//  dev/kmsg
[11] = { "kmsg", 0644, &kmsg_fops, 0 },
.mmap       = NULL,
mmap成员的实现
// 在 mmap 流程中 申请虚拟地址空间 并 设置 vma->vm_ops
shmem_zero_setup
	vma->vm_ops = &shmem_vm_ops;
mmap_zero
	shmem_zero_setup
		vma->vm_ops = &shmem_vm_ops;
shmem_mmap
	vma->vm_ops = &shmem_vm_ops;
		
// 在 访存时产生异常, 调用 vma->vm_op->fault , fault函数 中 会申请物理内存和 做映射
shmem_vm_ops
	shmem_fault
我们看到 /dev 下面的 文件 如果用到了 vma->vm_ops , 那么 一定是用到了 shmem_vm_ops
shmem_vm_ops 根据 tmpfs 的不同配置 会 重定位 到 shmem_vm_ops 或 generic_file_vm_ops


shmem_vm_ops 被 "共享匿名映射""共享文件映射 中的 /dev/zero""共享文件映射 中的 /dev/shm/xxx" 用到

// 其他的 vm_ops 使用场景
$ grep "vma->vm_ops = " * -nr 
drivers/usb/core/devio.c:271:   vma->vm_ops = &usbdev_vm_ops;
drivers/char/mem.c:403: vma->vm_ops = &mmap_mem_ops;
fs/kernfs/file.c:500:   vma->vm_ops = &kernfs_vm_ops;
fs/aio.c:369:   vma->vm_ops = &aio_ring_vm_ops;
fs/nfs/file.c:195:              vma->vm_ops = &nfs_file_vm_ops;
fs/ext4/file.c:766:             vma->vm_ops = &ext4_dax_vm_ops;
fs/ext4/file.c:769:             vma->vm_ops = &ext4_file_vm_ops;
include/linux/mm.h:641: vma->vm_ops = &dummy_vm_ops;
include/linux/mm.h:647: vma->vm_ops = NULL;
mm/shmem.c:2283:        vma->vm_ops = &shmem_vm_ops;
mm/shmem.c:4280:        vma->vm_ops = &shmem_vm_ops;
mm/filemap.c:3030:      vma->vm_ops = &generic_file_vm_ops;
mm/mmap.c:3500: vma->vm_ops = ops;
net/ipv4/tcp.c:1756:    vma->vm_ops = &tcp_vm_ops;

// 在系统初始化时 已经申请好了空间,在 mmap时 , 直接映射即可
fb_mmap
	vm_iomap_memory
mmap_mem
	remap_pfn_range
mmap_kmem
	mmap_mem
		remap_pfn_range
很少情况下会出现第二类
	在mmap前没做任何事情
	在mmap中做了虚拟地址空间的申请,物理地址空间的申请和映射关系的建立
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值