Chinaunix首页 | 论坛 | 博客
  • 博客访问: 174649
  • 博文数量: 38
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 458
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-09 11:22
文章分类

全部博文(38)

文章存档

2011年(1)

2010年(1)

2009年(8)

2008年(28)

我的朋友

分类: LINUX

2008-05-18 20:18:31

先上程序

/*----------------------part 1 start ----------------------------*/
/* Necessary includes for device drivers */
#include <linux/init.h>
//#include
#include <linux/module.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/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_from/to_user */
MODULE_LICENSE("Dual BSD/GPL");
/* Declaration of memory.c functions */
int memory_open(struct inode *inode, struct file *filp);
int memory_release(struct inode *inode, struct file *filp);
ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t memory_write(struct file *filp, char *buf,size_t count, loff_t *f_pos);
void memory_exit(void);
int memory_init(void);
/* Structure that declares the usual file */
/* access functions */
struct file_operations memory_fops = {
    read: memory_read,
    write: memory_write,
    open: memory_open,
    release: memory_release
};
/* Declaration of the init and exit functions */
module_init(memory_init);
module_exit(memory_exit);
/* Global variables of the driver */
/* Major number */
int memory_major = 60;
/* Buffer to store data */
char *memory_buffer;
/*----------------------part 1 end -----------------------------*/
/*----------------------part 2 start ---------------------------*/
int memory_init(void) {
    int result;
    /* Registering device */
    result = register_chrdev(memory_major, "memory",&memory_fops);
    if (result < 0) {
        printk("<1>memory: cannot obtain major number %d\n",memory_major);
        return result;
    }
    /* Allocating memory for the buffer */
    memory_buffer = kmalloc(1, GFP_KERNEL);
    if (!memory_buffer) {
        result = -ENOMEM;
        goto fail;
    }
    memset(memory_buffer, 0, 1);
    printk("<1>Inserting memory module\n");
    return 0;
    fail:
    memory_exit();
    return result;
}
/*----------------------part 2 end -----------------------------*/
/*----------------------part 3 start ---------------------------*/
void memory_exit(void) {
    /* Freeing the major number */
    unregister_chrdev(memory_major, "memory");
    /* Freeing buffer memory */
    if (memory_buffer) {
        kfree(memory_buffer);
    }
    printk("<1>Removing memory module\n");
}

/*----------------------part 3 end -----------------------------*/
/*----------------------part 4 start ---------------------------*/
int memory_open(struct inode *inode, struct file *filp)
{
    /* Success */
    return 0;
}
int memory_release(struct inode *inode, struct file*filp)
{
    /* Success */
    return 0;
}
/*----------------------part 4 end -----------------------------*/
/*----------------------part 5 start ---------------------------*/
ssize_t memory_read(struct file *filp, char *buf,size_t count, loff_t *f_pos) {
    /* Transfering data to user space */
    copy_to_user(buf,memory_buffer,1);
    /* Changing reading position as best suits */
    if (*f_pos == 0)
    {
        *f_pos+=1;
        return 1;
    }
    else {
        return 0;
    }
}
ssize_t memory_write( struct file *filp, char *buf,size_t count, loff_t *f_pos)
{
    char *tmp;
    tmp=buf+count-1;
    copy_from_user(memory_buffer,tmp,1);
    return 1;
}
/*----------------------part 5 end -----------------------------*/

说明:此程序使用电脑内存虚拟了一个硬件设备,他没有什么特别的硬件特性要初始化,只能实现简单的文字写入与读取

Part 1 :

在设备驱动中常用的 #include 声明;定义两了模块的初始化及卸载函数(对模块加载和卸载的时候被执行);定义了这个模块使用的主设备号为 60;定义一个字符型指针用来保存该驱动的数据(的起始地址)。

Part 2:

register_chrdev函数用于在内核空间,把驱动和/dev下设备文件链接在一起。它又三个参数:主设备号,模块名称和一个file_operations结构的指针。用于实现模块的安装代码。另外,代码使用了kmalloc函数。这个函数工作在内核空间,用于为该驱动程序的缓冲区分配内存。它和我们熟悉的malloc函数很相似。最后,如果注册主设备号或者分配内存失败,模块将退出。

Part 3:

通过memory_exit函数卸载模块,需要定义unregsiter_chrdev函数。这将释放驱动之前向内核申请的主设备号。同时缓冲区也需要通过该函数进行释放。

Part 4:

linux,所有设备都视为文件!例如网络、设备等。当设备文件被打开后,通常就需要初始化驱动的各个变量,对设备进行复位;当设备文件关闭后,通常需要释放该设备使用的内存,释放各种操作该设备相关的变量。但在本例中,这些操作都没进行。

Part 5:

和用户空间函数fread类似,内核空间里,读取设备文件使用read函数:read是file_operations的成员,用于调用register_chrdev。本例中,是memory_read函数。它的参数有:一个file结构;一个缓冲区(buf),用户空间的fread函数将从该缓冲区读数据;一个记录要传输的字节数量的计数器(count),它和用户空间的fread使用的计数器值相同;最后一个参数(f_pos)指示从哪里开始读取该设备文件。本例中,memory_read函数通过copy_to_user函数从驱动的缓冲区(memory_buffer)向用户空间传送一个简单的字节。设备文件的读取位置(f_pos)也改变了。如果起始点是文件的开头,那么f_pos的值将增加1,如果要读取的字节读取正常,则返回值为1。如果读取位置不是文件开头,则是文件的末尾,返回值将是0(因为文件只存储了 1 个字节)。

和用户空间里写文件的fwrite对应,内核空间里是write:write是file_operations的成员,用于调用register_chrdev。本例中是memory_write函数,它有如下几个参数:一个file结构;buf,一个缓冲区,用户空间函数fwrite将向该该缓冲区写数据;count,统计将传送的字节数的计数器,和用户空间函数fwrite的计数器有相同的数值;最后是f_pos,指示从哪里开始写文件。

运行结果

[root@HUNK 2]# ls
Makefile  memory.c~  memory.mod.c  memory.o
memory.c  memory.ko  memory.mod.o  Module.symvers
[root@HUNK 2]# insmod memory.ko
[root@HUNK 2]# echo "write data into memory-dev">/dev/memory
[root@HUNK 2]# cat /dev/memory
write data into memory-dev
[root@HUNK 2]#

 

 

阅读(1012) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~