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

本文所涉及到的源代码为 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"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值