⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ka.c

📁 我实现的一个基于零拷贝技术高速捕包的原型代码
💻 C
字号:
//开发支持用户访问核心内存的一个虚拟设备Kernel Agent,用于零拷贝
//作者:熊永平
//日期:2005年7月

#ifndef _KERNEL_
#	define _KERNEL_
#endif
#ifndef MODULE
#	define MODULE
#endif
#include<linux/config.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
#ifdef CONFIG_SMP
#define _SMP_
#endif
#define _NO_VERSION_		/* don't define kernel_verion in module.h */
#include<linux/version.h>

#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h>     /* everything... */
#include <linux/errno.h>  /* error codes */
#include <linux/types.h>  /* size_t */
#include <linux/fcntl.h>        /* O_ACCMODE */
#include<linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/ioctl.h>
#include<asm/segment.h>
#include<asm/pgtable.h>
#include<asm/page.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include "defs.h"

#undef PDEBUG             /* undef it, just in case */#ifdef KA_DEBUG#  ifdef __KERNEL__     /* This one if debugging is on, and kernel space */#    define PDEBUG(fmt, args...) printk( KERN_DEBUG "KA: " fmt, ## args)#  else     /* This one for user space */#    define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)#  endif#else#  define PDEBUG(fmt, args...) /* not debugging: nothing */#endif
#ifndef KA_MAJOR#define KA_MAJOR 0   /* dynamic major by default */#endif

char kernel_version[]=UTS_RELEASE;
uint ka_major=0;
ulong user_buff_addr = 0;
kernel_addr_space_t * base_addr;

static int open_ka(struct inode * node,struct file* file)
{
    MOD_INC_USE_COUNT;
    printk("<0>This is inside the open_test function\n");
    return 0;
};

static struct page * ka_vma_nopage(struct vm_area_struct * vma, unsigned long address, int unused)
{
	pgd_t *pgd;
	pmd_t *pmd;
	pte_t *pte;
	ulong offset = address - vma->vm_start;
	ulong addr = (ulong)base_addr+offset;
	struct page*page;

	/*防止其它 cpu改变页表,导致出错*/
	spin_lock(&init_mm.page_table_lock);
//取对应的物理页地址
	pgd = pgd_offset (current -> mm,(unsigned long)addr);
	pmd = pmd_offset (pgd,(unsigned long)addr) ;
	pte = pte_offset (pmd,( unsigned long)addr);

	spin_unlock(&init_mm.page_table_lock);

	page = pte_page(*pte);
	/* got it, now increment the count */
	get_page(page);

	return  page;
}

static struct vm_operations_struct ka_vm_ops =
    {
        .nopage	= 	ka_vma_nopage,
    };

static int mmap_ka (struct file * file, struct vm_area_struct * vma)
{
	unsigned long size = (unsigned long)(vma->vm_end-vma->vm_start);

	printk(KERN_INFO "ka_mmap called\n");

	if (size > sizeof(kernel_addr_space_t))
	    return -EINVAL;

	vma->vm_ops = &ka_vm_ops;

	//vma - > vm_flags | = VM- RESERVED;
	//ka_vma_open( vma) ;
	
	return 0 ;
	}

static int close_ka(struct inode *inode, struct file *file)
{
	MOD_DEC_USE_COUNT;
	return 0;
}


 int ioctl_ka (struct inode *inode, struct file *filp,uint cmd, ulong arg)
{

	int error = 0;
	uint i;
	ulong addr;	

	switch(cmd)
	{
	case KA_IOCINITBUF:
		error = copy_from_user(&user_buff_addr, (void *)arg, sizeof(unsigned long));
		if (error)
			return error;
		break;

	default:  /* redundant, as cmd was checked against MAXNR */
	    return -EINVAL;
	}

	user_buff_addr = PAGE_ALIGN(user_buff_addr);

	base_addr = vmalloc(sizeof(kernel_addr_space_t));
	if(!base_addr)
	    return -ENOMEM;

	base_addr->rx_q.size = RX_BUFF_BLK_NUM;
	base_addr->rx_q.head = base_addr->rx_q.tail = 0;
	memset(base_addr->rx_q.elem,0,base_addr->rx_q.size * sizeof(uint));

	base_addr->tx_q.size = TX_BUFF_BLK_NUM;
	base_addr->tx_q.head = base_addr->tx_q.tail = 0;
	memset(base_addr->tx_q.elem,0,base_addr->tx_q.size * sizeof(uint));	/*just initialize enough size memory */

	base_addr->free_q.size = BUFF_BLK_NUM;
	base_addr->free_q.head = base_addr->free_q.tail = 0;
	memset(base_addr->free_q.elem,0,base_addr->free_q.size * sizeof(uint));

	for(i=0;i<BUFF_BLK_NUM;i++)
	    enqueue(&(base_addr->free_q),i);

	/*initialize physical address table */
	addr = user_buff_addr;
	for(i=0;i<(BUFF_BLK_NUM>>1);i++,addr+=PAGE_SIZE)
	{
	    struct page*page;
	    pgd_t *pgd = pgd_offset (current -> mm,(unsigned long)addr);
	    pmd_t *pmd = pmd_offset (pgd,(unsigned long)addr) ;
	    pte_t *pte = pte_offset (pmd,( unsigned long)addr);
	    base_addr->phy_addr_table [i] = pte_val(*pte) & PAGE_MASK;

	    page = pte_page (*pte) ;

	    //set_ bit( PG- locked , &page - > flags) ;

	    atomic_inc (&(page->count));
	}

	return 0;

}



struct file_operations ka_ops=
{
	.ioctl	=	ioctl_ka,
	.mmap	=	mmap_ka,
	.open	=	open_ka,
	.release	=	close_ka,
};

int init_module(void)
{
	printk("<0>This is the init part!\n");
	int result;
	result=register_chrdev(0,"great",&ka_ops);
	if(result<0)
	{
		printk("<0>test :Can't get major number\n");
		return result;
	}
	if(ka_major==0)
		ka_major=result;
	return 0;
}

void cleanup_module(void)
{
	printk("<0>This is inside the cleanup_module function!\n");
	unregister_chrdev(ka_major,"great");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -