📄 ka.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 + -