课堂实践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>结束--------------------- */