Memory驱动分析

课堂实践3

简单Memory驱动程序

//memory.c 文件
/* Necessary includes for device drivers */

#include <linux/init.h>
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/cdev.h>  //linux2.6设备驱动的头文件,包含cdev_alloc、cdev_init、cdev_add和cdev_del函数的定义
#include <linux/device.h>  //class_create(),class_destroy(),class_device_create(),class_device_destroy()函数定义在device.h头文件中
#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, const 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 = {
	.owner = THIS_MODULE,
	.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 = 360;

/* 设备号 */
dev_t dev_num;
static struct cdev *pcdev;
struct class *myclass=NULL;
/* Buffer to store data */
char *memory_buffer;

/* ------------------<memory init module>开始--------------------- */
//该段代码使用了kmalloc函数。这个函数工作在内核空间,用于为该驱动程序的缓冲区分配内存。
//它和我们熟悉的malloc函数很相似。最后,如果注册主设备号或者分配内存失败,模块将退出。
int memory_init(void) 
{
	int result = -1;
	/* Registering device */
	//result = register_chrdev(memory_major, "memory", &memory_fops);
	 //动态申请一个 字符设备内存。
	pcdev = cdev_alloc();
        //字符设备初始化
	cdev_init(pcdev, &memory_fops);
	//动态注册一个字符设备
	result = alloc_chrdev_region(&dev_num, 0, 1, "my_memory");  //次设备号从0开始,注册1个设备,设备名为my_memory。	
	printk("<0>major = %d, minor = %d\n", MAJOR(dev_num), MINOR(dev_num));
	pcdev->owner = THIS_MODULE;

        //向系统中 添加一个字符设备
	cdev_add(pcdev, dev_num, 1);

	//创建设备文件
	myclass=class_create(THIS_MODULE, "test");
	//利用udev创建设备文件创建设备文件,linux2.26及以后的版本,可能用device_create()
	//class_device_create(myclass,NULL,dev_num,NULL,"my_memory"); //error: implicit declaration of function 'class_device_create'
	device_create(myclass, NULL, dev_num, NULL,"my_memory");
	
	printk("<0>test_init ok,device create ok\n");
	
	/* Allocating memory for the buffer */
	memory_buffer = kmalloc(1, GFP_KERNEL);
	if (!memory_buffer) {
		result = -ENOMEM;
		goto fail;
	}
	memset(memory_buffer, 0, 1);
	printk("<0>Inserting memory module\n");
	return 0;
	fail:
		memory_exit();
		return result;
}
/* ------------------<memory init module>结束--------------------- */


/* ------------------<memory exit module>开始--------------------- */
//为了完全的卸载该驱动,缓冲区也需要通过该函数进行释放。
void memory_exit(void) 
{
	/* Freeing the major number */
	//unregister_chrdev(memory_major, "memory");
 	// 从系统中删除字符设备
        cdev_del(pcdev);
        //注销字符设备
        unregister_chrdev_region(dev_num, 1);
        
	//删除/dev目录下相应的设备文件,linux2.26及以后的版本,可能用device_destroy()
	//class_device_destroy(myclass,dev_num);	//error: implicit declaration of function 'class_device_destroy'
	//device_destroy(myclass);			//error: too few arguments to function 'device_destroy'
	device_destroy(myclass, dev_num);
	
	/* Freeing buffer memory */
	if (memory_buffer) {
		kfree(memory_buffer);
	}
	printk("<0>Removing memory module\n");
}
/* ------------------<memory exit module>结束--------------------- */

/* ------------------<memory open>开始--------------------- */
//当设备文件被打开后,通常就需要初始化驱动的各个变量,对设备进行复位。但在本例中,这些操作都没进行。
int memory_open(struct inode *inode, struct file *filp)
{
	/* Success */
	return 0;
}
/* ------------------<memory open>结束--------------------- */


/* ------------------<memory release>开始--------------------- */
//当设备文件关闭后,通常需要释放该设备使用的内存,释放各种操作该设备相关的变量。但是,为简单起见,例子里没有进行这些操作。
int memory_release(struct inode *inode, struct file *filp) 
{
	/* Success */
	return 0;
}
/* ------------------<memory release>结束--------------------- */


/* ------------------<memory read>开始--------------------- */
//本例中,memory_read函数通过copy_to_user函数从驱动的缓冲区(memory_buffer)向用户空间传送一个简单的字节。
ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
	unsigned long ret;	
	/* Transfering data to user space */
	ret = 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;
	}
}
/* ------------------<memory read>结束--------------------- */


/* ------------------<memory write>开始--------------------- */
//本例中的memory_write函数,它有如下几个参数:
//一个file结构;
//buf,一个缓冲区,用户空间函数fwrite将向该该缓冲区写数据;
//count,统计将传送的字节数的计数器,和用户空间函数fwrite的计数器有相同的数值;
//最后是f_pos,指示从哪里开始写文件。。
ssize_t memory_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
	//char *tmp;
	unsigned long ret;
	//tmp=buf+count-1;
	ret = copy_from_user(memory_buffer,buf+count-1, 1);
	return 1;
}
/* ------------------<memory write>结束--------------------- */

编译的的时候,开发板可以正常加载,虚拟机里面red hat 5.5下面编译没问题,但是加载模块,虚拟机会卡死,暂时没解决,可能是 main函数 动态创建设备的问题,先不搞了, 留着。

你可能感兴趣的:(Memory驱动分析)