内核态到用户态数据传输的几种方式
内核态-用户态数据传输方式
参考: https://blog.csdn.net/bingqingsuimeng/article/details/7924756
1. 数据拷贝(copy_to_user, copy_from_user)
这个就是一个简单的数据拷贝, 跟用户态的 拷贝函数 memcpy 差不多, 其性能也是相差不多, 不过速率较低
示例代码: https://gitee.com/han_gx/my_notes/tree/master/linux_C/driver_test
2. 内存映像(mmap)
首先这里内存映射包含两个方面
- 内核态到硬件上的内存映射
内核态和硬件之间数据大量的传输,需要映射到虚拟内存上,以PCIE设备为例(目前就接触PCIE这块),内核态会申请一块用于DMA的虚拟内存, 然后将物理地址传输给fpga, fpga给定的物理地址写入固定大小数据即可.物理地址由内核固定的接口提供,经过验证,直接对物理地址不能进行偏移,读写等操作.(验证方法,将要偏移的大小传至fpga,fpga将起始物理地址进行一定的偏移,和内核态对起始物理地址进行偏移,偏移过后的地址不一致) - 用户态到内核态的内存映射
用户态直接使用mmap接口, 在内核态需要对mmap函数进行重载,负责会调用失败.
示例代码, 这里是一个PCIE驱动,其中包含了对用户态到内核态的mmap,并在驱动程序中重写了 mmap:
驱动代码: https://gitee.com/han_gx/linux_cpu/tree/48T/xbmd_drv
用户调用: https://gitee.com/han_gx/linux_cpu/tree/48T/xbmd_test
/dev/mem
介绍: 在liunx和嵌入式linux当中,基本上都有 dev/mem
设备, 该设备是内核所有物理地址空间的全映像,这些地址包括: 物理内存(RAM)空间、物理存储(ROM)空间、CPU总线地址、CPU寄存器地址、外设寄存器地址、GPIO、定时器、ADC、DMA地址空间等. 缺点: 非法访问导致系统不稳定,甚至内核崩溃
对/dev/mem源码解读
通过源码修改解除/dev/mem的某些限制
使用方法: dev/mem
与 mmap
结合
int fd = 0;
char *mmap_addr = NULL;
unsigned char *mmap_addr = 0x12345678; //这里代表内存的物理地址, 可以是其内核申请获得的物理地址,也可以是用户态申请获得的物理地址
fd = open("/dev/mem", O_RDWR | O_NDELAY); /* 读写权限,非阻塞 */
mmap_addr=(char *)mmap(NULL, MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mmap_addr);
扩展:
- hexdump -n 32 -s 2 /dev/mem, 可以通过偏移量和长度查看/dev/mem物理地址的值
- /dev/kmem(不是必然存在的) 可以查看内核虚拟内存的全镜像,查看对应地址的变量等
3. proc 文件系统
4. 虚拟文件系统
5. 信号量
6.由内核主动发起的信息交互
本文来自博客园踩坑狭,作者:韩若明瞳,转载请注明原文链接:https://www.cnblogs.com/han-guang-xue/p/16531720.html