您的位置:首页 > 运维架构 > Linux

Linux内核zero-copy小试牛刀(加注释)

2015-12-01 23:48 501 查看
本文所涉及到的源代码为 wheelz原创,freas_1990加工整理。转载请标明出处:http://blog.csdn.net/freas_1990/article/details/19653015

偶然在网上偶然翻到一篇 wheelz在多年前写的通过mmap + /dev/mem + 共享内存来实现zero-copy的文章, wheelz在网上已经很久没路面了,本文 简单加批注如下。

模块程序:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wheelz");
MODULE_DESCRIPTION("mmap demo");

static unsigned long p = 0;
static int __init init(void) {
//分配共享内存(一个页面)
p = __get_free_pages(GFP_KERNEL, 0);
SetPageReserved(virt_to_page(p));
//这里的地址会被记录到/var/log/message文件里面去,
//用户空间的程序里的读取地址是人工从该文件里面“看”出来,然后再手工添加到代码里去
printk("<1> p = 0x%08x\n", p);
//在共享内存中写上一个字符串
strcpy(p, "Hello world!\n");
return 0;
}

static void __exit fini(void) {
ClearPageReserved(virt_to_page(p));
free_pages(p, 0);
}

module_init(init);
module_exit(fini);

用户态程序:
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#define PAGE_SIZE (4*1024)
#define PAGE_OFFSET		0xc0000000
#define KERNEL_VIRT_ADDR	0xc5e3c000    //这个地址需要读取/var/log/message查看,每台机器每次运行都需要修改

int main() {
char *buf;
int fd;
unsigned long phy_addr;
//这里的/dev/mem是整个物理地址空间的映射
fd=open("/dev/mem",O_RDWR);
if(fd == -1)
perror("open");
phy_addr=KERNEL_VIRT_ADDR - PAGE_OFFSET;
//通过mmap映射物理地址到user space的虚拟地址
//由于/dev/mem映射的是物理地址空间,所以start设置为NULL,这样offset就可以直接设置成物理地址。
buf=mmap(NULL, PAGE_SIZE,
PROT_READ|PROT_WRITE, MAP_SHARED,
fd, phy_addr);
if(buf == MAP_FAILED)
perror("mmap");
puts(buf);//打印共享内存的内容
munmap(buf,PAGE_SIZE);
close(fd);
return 0;
}

Makefile如下:
ifneq ($(KERNELRELEASE),)
obj-m:=mod.o
else
KDIR := /lib/modules/$(shell uname -r)/build
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
endif

运行用户态程序的时候,可能会报一个莫名其妙的错误:
mmap: Operation not permitted
segmentation fault

这个问题是内核配置引起的,把以下三个选项设置下:
CONFIG_STRICT_DEVMEM=n
CONFIG_X86_PAT=n
CONFIG_EXPERT=y

最后再附上module的常用命令:

加载名字为mod的模块
#insmod ./mod


查看名为mod的module
#lsmod |grep "mod"

删除名为mod的模块
#lsmod |grep "mod"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: