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在网上已经很久没路面了,本文 简单加批注如下。
模块程序:
用户态程序:
Makefile如下:
运行用户态程序的时候,可能会报一个莫名其妙的错误:
这个问题是内核配置引起的,把以下三个选项设置下:
最后再附上module的常用命令:
加载名字为mod的模块
查看名为mod的module
删除名为mod的模块
偶然在网上偶然翻到一篇 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"
相关文章推荐
- Linux文件所用到的系统调用的函数总结
- linux socket 编程(C语言)--转载
- 软中断网卡处理&Linux高性能外部设备处理机制
- Linux五个查找命令
- linux下virtualbox和wine
- Linux内核网卡收包机制历史变革
- 从linux的findso、finda命令所想到的------所想即所得与所见即所得
- Linux keepalived与lvs的深入分析
- Linux内核的信号机制——怪胎
- Linux下配置文件读取操作流程及其C代码实现
- 我的VPS选择之路
- linux命令复用技巧
- Linux学习笔记(3)之文件操作
- Linux负载均衡软件之LVS
- linux下如何设置vip(虚拟ip)
- Linux下select&poll&epoll的实现原理(一)
- linux软件包管理
- linux命令编辑技巧
- RHEL6忘记root密码的解决办法
- CentOS排错