Linux内核空间映射到用户空间
2015-08-31 16:57
846 查看
***************************************************************************************************************************
作者:EasyWave 时间:2012.12.26
类别:Linux内核- 内核空间映射 声明:转载,请保留链接
注意:如有错误,欢迎指正。这些是我学习的日志文章......
***************************************************************************************************************************
一:简介
共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据。一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。
二:实例应用
Linux的2.2.x内核支持多种共享内存方式,如mmap()系统调用,Posix共享内存,以及系统V共享内存。当内核空间和用户空间存在大量数据交互时, 共享内存映射就成了这种情况下的不二选择; 它能够最大限度的降低内核空间和用户空间之间的数据拷贝, 从而大大提高系统的性能.
以下是创建从内核空间到用户空间的共享内存映射的模板代码(在内核2.6.18和2.6.32上测试通过):
1.内核空间分配内存
[cpp] view
plaincopyprint?
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
int mmap_alloc(int require_buf_size)
{
struct page *page;
mmap_size = PAGE_ALIGN(require_buf_size);
#if USE_KMALLOC //for kmalloc
mmap_buf = kzalloc(mmap_size, GFP_KERNEL);
if (!mmap_buf) {
return -1;
}
for (page = virt_to_page(mmap_buf ); page < virt_to_page(mmap_buf + mmap_size); page++) {
SetPageReserved(page);
}
#else //for vmalloc
mmap_buf = vmalloc(mmap_size);
if (!mmap_buf ) {
return -1;
}
for (i = 0; i < mmap_size; i += PAGE_SIZE) {
SetPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf) + i)));
}
#endif
return 0;
}
2.用户空间映射内存
[cpp] view
plaincopyprint?
int test_mmap()
{
mmap_fd = open("/dev/mmap_dev", O_RDWR);
mmap_ptr = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, mmap_fd, 0);
if (mmap_ptr == MAP_FAILED) {
return -1;
}
return 0;
}
3.内核空间映射内存: 实现file_operations的mmap函数
[cpp] view
plaincopyprint?
static int mmap_mmap(struct file *filp, struct vm_area_struct *vma)
{
int ret;
unsigned long pfn;
unsigned long start = vma->vm_start;
unsigned long size = PAGE_ALIGN(vma->vm_end - vma->vm_start);
if (size > mmap_size || !mmap_buf) {
return -EINVAL;
}
#if USE_KMALLOC
return remap_pfn_range(vma, start, (virt_to_phys(mmap_buf) >> PAGE_SHIFT), size, PAGE_SHARED);
#else
/* loop over all pages, map it page individually */
while (size > 0) {
pfn = vmalloc_to_pfn(mmap_buf);
if ((ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) < 0) {
return ret;
}
start += PAGE_SIZE;
mmap_buf += PAGE_SIZE;
size -= PAGE_SIZE;
}
#endif
return 0;
}
static const struct file_operations mmap_fops = {
.owner = THIS_MODULE,
.ioctl = mmap_ioctl,
.open = mmap_open,
.mmap = mmap_mmap,
.release = mmap_release,
};
4.用户空间撤销内存映射
[cpp] view
plaincopyprint?
void test_munmap()
{
munmap(mmap_ptr, mmap_size);
close(mmap_fd);
}
5.内核空间释放内存; 必须在用户空间执行munmap系统调用后才能释放
[cpp] view
plaincopyprint?
void mmap_free()
{
#if USE_KMALLOC
struct page *page;
for (page = virt_to_page(mmap_buf); page < virt_to_page(mmap_buf + mmap_size); page++) {
ClearPageReserved(page);
}
kfree(mmap_buf);
#else
int i;
for (i = 0; i < mmap_size; i += PAGE_SIZE) {
ClearPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf) + i)));
}
vfree(mmap_buf);
#endif
mmap_buf = NULL;
}
对于大数据的内存访问,一般来说在Linux系统中采用内存映射是最好的方式,这样对于应用层来说,可以很方便的访问到内核的空间..
from: http://blog.csdn.net/wavemcu/article/details/8441072
作者:EasyWave 时间:2012.12.26
类别:Linux内核- 内核空间映射 声明:转载,请保留链接
注意:如有错误,欢迎指正。这些是我学习的日志文章......
***************************************************************************************************************************
一:简介
共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据。一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。
二:实例应用
Linux的2.2.x内核支持多种共享内存方式,如mmap()系统调用,Posix共享内存,以及系统V共享内存。当内核空间和用户空间存在大量数据交互时, 共享内存映射就成了这种情况下的不二选择; 它能够最大限度的降低内核空间和用户空间之间的数据拷贝, 从而大大提高系统的性能.
以下是创建从内核空间到用户空间的共享内存映射的模板代码(在内核2.6.18和2.6.32上测试通过):
1.内核空间分配内存
[cpp] view
plaincopyprint?
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
int mmap_alloc(int require_buf_size)
{
struct page *page;
mmap_size = PAGE_ALIGN(require_buf_size);
#if USE_KMALLOC //for kmalloc
mmap_buf = kzalloc(mmap_size, GFP_KERNEL);
if (!mmap_buf) {
return -1;
}
for (page = virt_to_page(mmap_buf ); page < virt_to_page(mmap_buf + mmap_size); page++) {
SetPageReserved(page);
}
#else //for vmalloc
mmap_buf = vmalloc(mmap_size);
if (!mmap_buf ) {
return -1;
}
for (i = 0; i < mmap_size; i += PAGE_SIZE) {
SetPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf) + i)));
}
#endif
return 0;
}
2.用户空间映射内存
[cpp] view
plaincopyprint?
int test_mmap()
{
mmap_fd = open("/dev/mmap_dev", O_RDWR);
mmap_ptr = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, mmap_fd, 0);
if (mmap_ptr == MAP_FAILED) {
return -1;
}
return 0;
}
3.内核空间映射内存: 实现file_operations的mmap函数
[cpp] view
plaincopyprint?
static int mmap_mmap(struct file *filp, struct vm_area_struct *vma)
{
int ret;
unsigned long pfn;
unsigned long start = vma->vm_start;
unsigned long size = PAGE_ALIGN(vma->vm_end - vma->vm_start);
if (size > mmap_size || !mmap_buf) {
return -EINVAL;
}
#if USE_KMALLOC
return remap_pfn_range(vma, start, (virt_to_phys(mmap_buf) >> PAGE_SHIFT), size, PAGE_SHARED);
#else
/* loop over all pages, map it page individually */
while (size > 0) {
pfn = vmalloc_to_pfn(mmap_buf);
if ((ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) < 0) {
return ret;
}
start += PAGE_SIZE;
mmap_buf += PAGE_SIZE;
size -= PAGE_SIZE;
}
#endif
return 0;
}
static const struct file_operations mmap_fops = {
.owner = THIS_MODULE,
.ioctl = mmap_ioctl,
.open = mmap_open,
.mmap = mmap_mmap,
.release = mmap_release,
};
4.用户空间撤销内存映射
[cpp] view
plaincopyprint?
void test_munmap()
{
munmap(mmap_ptr, mmap_size);
close(mmap_fd);
}
5.内核空间释放内存; 必须在用户空间执行munmap系统调用后才能释放
[cpp] view
plaincopyprint?
void mmap_free()
{
#if USE_KMALLOC
struct page *page;
for (page = virt_to_page(mmap_buf); page < virt_to_page(mmap_buf + mmap_size); page++) {
ClearPageReserved(page);
}
kfree(mmap_buf);
#else
int i;
for (i = 0; i < mmap_size; i += PAGE_SIZE) {
ClearPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf) + i)));
}
vfree(mmap_buf);
#endif
mmap_buf = NULL;
}
对于大数据的内存访问,一般来说在Linux系统中采用内存映射是最好的方式,这样对于应用层来说,可以很方便的访问到内核的空间..
from: http://blog.csdn.net/wavemcu/article/details/8441072
相关文章推荐
- 从 Linux 内核访问用户空间内存
- Hadoop第6周练习—在Eclipse中安装Hadoop插件及测试(Linux操作系统)
- nagios监控linux设置
- nagios监控linux设置
- 跟马哥学linux (lesson 3)
- Linux的inode的理解
- Linux下配置Java web服务器
- Linux 内核学习之内存管理(一) 总体描述
- Linux下,多线程程序死循环问题调试
- Xshll 登陆linux很慢解决方式
- linux环境变量
- Linux基础三(常见命令大全)
- Linux 硬件信息查看的命令
- linux批量转换整个目录下的文件编码为UTF-8
- Linux makefile 教程 非常详细,且易懂
- tac命令以及各种linux文件查看命令
- 在 Linux 下使用 RAID(五):安装 RAID 6(条带化双分布式奇偶校验)
- 在 Linux 下使用 RAID(五):安装 RAID 6(条带化双分布式奇偶校验)
- Linux系统信息查看命令大全
- linux开机启动