(a)通过kernel命令行参数预留一些内存
这种方法,适合于需要大块的物理连续的内存。
假设物理内存总量为256M。命令行参数中,指定 mem=224M。即只让内核使用前224M内存,忽略其余的内存。
这样,我们就有了32M的内存可用,内存起始物理地址为224*1024*1024。
在内核态,通过ioremap,就可以将此物理地址处的内存映射到内核空间。
不过,这种方法好像在X86_64架构下会有问题。在arm上,则没有发现问题。
有高手知道原因,还望指导一下^_^
(b)直接从内核申请一块内存
通过__get_free_pages(GFP_KERNEL,n); 从内核申请n个内存页。n好像必须是2的整数次方。
二、将内存映射到用户空间
通过上面的工作,内核中已经得到了此内存的虚拟地址,当然这是内核空间的虚拟地址。我们假设此地址保存在了void *rsv_mem变量中。
接下来把他映射到用户空间。这个工作分两部分。一部分是内核态的工作,一部分是用户态的工作。
1. 内核态的工作
在内核态调用misc_register注册一个设备,此设备的其他方面,我们就不说了。
只说说file_operations中的mmap成员的实现。这个实现很简单,代码如下:
static int soft_wdt_mmap(struct file *filp, struct vm_area_struct *vma)
{
unsigned long pfn = (virt_to_phys(rsv_mem) >> PAGE_SHIFT);
if (remap_pfn_range(vma, vma->vm_start, pfn,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
return 0;
}
2. 用户态的工作
假设内存大小是8192字节。
int fd=open("/dev/my_dev", O_RDWR);
void *ptr_dev_mem==mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
好了,这就完成了用户态的映射了。
实际上,要想方便的应用内存共享,实现高性能的业务处理,还有一些工作要做。
以生产者、消费者为例,可以这样实现具体的应用。
内核态驱动将这块映射好的大内存分成很多块小的buffer,放到一个buffer pool中管理起来。
同时,内核态驱动创建一个队列,里面存放待消费的内容。
然后,内核态的驱动需要实现poll函数,以便用户态程序能够使用poll或select查询有没有待消费的内容。
另外,内核驱动还需要实现一组ioctl函数,以便用户态获取队列中的buffer信息。
最后,在内核态中创建一个生产者线程,他不断的从buffer pool中申请一个buffer,填入数据后,将他送入队列。
用户态程序实现消费者。
消费者打开设备文件,并完成内存映射后,通过select或poll操作,就知道当前有没有待消费的内容。
若有,则可以通过ioctl系统调用(可以定义一个无阻塞的命令),进入内核态,内核态则将队列首部的buffer做出队操作,并返回此buffer的信息(例如,内核态根据buffer的内核态地址返回此buffer的索引号)。用户态就可以根据返回的信息,得到此buffer的用户态地址,进行消费。消费之后,再通过ioctl系统调用,告诉内核将此buffer释放回buffer pool。内核与用户态之间,还可以定义一个阻塞模式的ioctl命令,用户态用此命令获取buffer,若当前队列无buffer,则将消费者挂起,直到有buffer入列了,或者消费者收到了信号。
一、首先获取一块物理上连续的物理内存有多种方法。(a)通过kernel命令行参数预留一些内存这种方法,适合于需要大块的物理连续的内存。假设物理内存总量为256M。命令行参数中,指定 mem=224M。即只让内核使用前224M内存,忽略其余的内存。这样,我们就有了32M的内存可用,内存起始物理地址为224*1024*1024。在内核态,通过ioremap,就可以将此物理地址处
例子中,
用户
态
程序
的KERNEL_VIRT_ADDR就是
内核
模块打印的地址p ,这里是hard coding(先加载
内核
模块,再把打印的地址赋值给KERNEL_VIRT_ADDR),
可以采用其他的方式传递。
2.6
内核
验证。
//kernel
#include linux/config.h>
#include linux/module.h>
#inclu
用
内存
映射在多个应用
程序
之间
共享
数据,使用
(1)用CreateFileMapping()创建一个文件映射
内核
对象;
(2)用MapViewOfFile()将文件数据映射到进程的地址空间;
(3)用UnmapViewOfFile()从进程地址空间解除这个映射。
Linux
内核
态
和
用户
态
共享
内存
1、mmap系统调用(功能)
void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset )
内存
映射函数mmap,
负责把文件内容映射到进程的虚拟
内存
空间,
通过对这段
内存
的读取和修改,来实现对文件的读取和修改,而不需要再
在
用户
态
分配的空间需要使用free() 回收。
内核
态
内存
分配
在
内核
态
可以使用kmalloc()、vmalloc()、kzalloc()、vzalloc()分配
内存
,区别如下:
void * kmalloc(size_t si
内核
空间和
用户
空间交换数据的方式有很多。
用户
空间发起的有系统调用、proc、虚拟文
件系统等。
内核
空间主动发起的有get_user/put_user、信号、netlink等。
Linux应用
程序
与
内核
程序
交互主要有以下几种通信方式:
(1)系统调用
Linux系统下,设备即文件,也因此大部分设备驱动...