0、我的理解,所为驱动,就是用户可以通过自己的应用程序访问你的文件系统。而我恰恰相反。
1、我是谢了字符驱动,让我的fileSystem去做应用程序,同样可以被linux系统识别。
2、其实我对驱动理解也不深,暂且贴代码。
3、驱动程序:
/*chardev.c 驱动程序*/ #include <linux/kernel.h> #include <linux/fs.h>/*for file-f_op*/ #include <linux/module.h> #include <asm/uaccess.h>/*for copy_to_user()*/ #include <linux/cdev.h>/*for cdev ,cdev_init,cdev_add....*/ MODULE_AUTHOR("MMC"); MODULE_LICENSE("GPL"); #define DP_MAJOR 250 /*the major number of the chardev*/ #define DP_MINOR 0 /*the minor number of the chardev*/ #define CHARDEV_SIZE 512*500 static int chropen;/*the chardev open or not*/ struct cdev *chardev;/*define a char device*/ char char_dev_data[CHARDEV_SIZE]; static int char_read(struct file *filp, char __user *buffer, size_t, loff_t *); /*read the data from kernel*/ static int char_write(struct file *filp, const char __user *buffer, size_t, loff_t *); /*write data to kernel*/ static int char_open(struct inode *,struct file *); /*open the chardev*/ static int char_release(struct inode *, struct file *); /*release the chardev*/ static loff_t char_llseek(struct file *filp, loff_t offset, int whence); /*文件操作结构体*/ static const struct file_operations char_fops = { .owner = THIS_MODULE, .llseek = char_llseek, .read = char_read, .write = char_write, .open = char_open, .release = char_release, }; static int __init char_init(void) { dev_t devno; printk(KERN_ALERT"Initing......\n"); devno=MKDEV(DP_MAJOR,DP_MINOR); chardev=cdev_alloc( ); if(chardev==NULL) { return -1; } if(register_chrdev_region(devno,10,"chardev"))//注册设备号 { printk(KERN_ALERT"Register char dev error\n"); return -1; } chropen=0; cdev_init(chardev,&char_fops);//初始化cdev if(cdev_add(chardev,devno,1))//添加cdev到系统 { printk(KERN_ALERT"Add char dev error\n"); } memset(char_dev_data, 0, CHARDEV_SIZE);//set data return 0; } /*文件打开函数*/ static int char_open(struct inode *inode, struct file *file) { if(chropen==0) { chropen++; } else { printk(KERN_ALERT"Another process open the char device\n"); return -1; } try_module_get(THIS_MODULE); return 0; } /*读函数*/ static ssize_t char_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) { unsigned long p = *ppos;/*记录文件指针偏移位置*/ unsigned int count = size;/*记录需要读取的字节数*/ int ret = 0;/*返回值*/ /*判断读位置是否有效*/ if (p >= CHARDEV_SIZE)/*要读取的偏移大于设备的内存空间*/ return -1; if (count > CHARDEV_SIZE - p)/*要读取的字节大于设备的内存空间*/ count = CHARDEV_SIZE - p; /*读数据到用户空间:内核空间->用户空间交换数据*/ if (copy_to_user(buf, char_dev_data + p, count)) { ret = -EFAULT; } else { *ppos += count; ret = count; printk(KERN_INFO "read %d bytes(s) from %d\n", count, p); } return ret; } /*写函数*/ static ssize_t char_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos) { unsigned long p = *ppos; unsigned int count = size; int ret = 0; /*分析和获取有效的写长度*/ if (p >= CHARDEV_SIZE) return -1; if (count > CHARDEV_SIZE - p)/*要写入的字节大于设备的内存空间*/ count = CHARDEV_SIZE - p; /*从用户空间写入数据*/ if (copy_from_user(char_dev_data + p, buf, count)) ret = -EFAULT; else { *ppos += count; /*增加偏移位置*/ ret = count; /*返回实际的写入字节数*/ printk(KERN_INFO "written %d bytes(s) from %d\n", count, p); } return ret; } /* seek文件定位函数 */ static loff_t char_llseek(struct file *filp, loff_t offset, int whence) { loff_t newpos; switch(whence) { case 0: /* SEEK_SET */ /*相对文件开始位置偏移*/ newpos = offset; /*更新文件指针位置*/ break; case 1: /* SEEK_CUR */ newpos = filp->f_pos + offset; break; case 2: /* SEEK_END */ newpos = CHARDEV_SIZE -1 + offset; break; default: /* can‘t happen */ return -EINVAL; } if ((newpos<0) || (newpos>CHARDEV_SIZE)) return -EINVAL; filp->f_pos = newpos; return newpos; } /*文件释放函数*/ static int char_release(struct inode *inode, struct file *file) { chropen--; module_put(THIS_MODULE); return 0; } static void __exit char_exit(void) { printk(KERN_ALERT"Unloading..........\n"); unregister_chrdev_region(MKDEV(DP_MAJOR,DP_MINOR),10);//注销cdev设备号 cdev_del(chardev);//从系统删除设备cdev } module_init(char_init); module_exit(char_exit);
4、Makefile:
ifneq ($(KERNELRELEASE),) obj-m := chardev.o else KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif
5、配置命令:
1)创建Makefile文件: 2)执行make命令: [email protected]-vm:/usr/mmc/dirPro/charDri# make 3)将生成的驱动模块插入内核: [email protected]-vm:/usr/mmc/dirPro/charDri# insmod ./chardev.ko 4)查看插入后的情况: [email protected]-vm:/usr/mmc/dirPro/charDri# lsmod 5)设备节点的创建: [email protected]-vm:/usr/mmc/dirPro/charDri# mknod /dev/chardev0 c 250 0 6)编译用户程序gcc -o chardev_test main.c [email protected]-vm:/usr/mmc/dirPro/charDri# gcc -o test test.c -std=c99 7)运行chmod 666 /dev/chardev0 使其它用户也可以对这个设备进行读写操作,否则只有root用户可以对它进行读写。 [email protected]-vm:/usr/mmc/dirPro/charDri# chmod 666 /dev/chardev0 8)运行test [email protected]-vm:/usr/mmc/dirPro/charDri# ./test 9)删除设备节点,就像删除普通文件一样: [email protected]-vm:/usr/mmc/dirPro/charDri# rm /dev/chardev0 10)卸载内核驱动模块 [email protected]-vm:/usr/mmc/dirPro/charDri# rmmod chardev.ko 11)重新运行test,观察结果 12)重新插入内核驱动模块和设备节点,又可以正常显示结果
6、测试程序:
刚才说了,就是filesystem的程序,但是需要把之前的fopen、fclose、fwrite、fread、fseek改为系统调用函数open、close、write、read、lseek即可。
//fileSystemPointer=fopen(fileSystemName,"wb");//读写打开一个二进制文件
fileSystemPointer=open(fileSystemName, O_RDWR, S_IRUSR|S_IWUSR);
//fseek(fileSystemPointer,0,SEEK_SET);
lseek(fileSystemPointer,0,SEEK_SET);
//fwrite(&superBlock,sizeof(struct SuperBlock),1,fileSystemPointer);//4个BLOCK
write(fileSystemPointer,&superBlock,sizeof(struct SuperBlock));//4个BLOCK
7、参考资料:
LINUX设备驱动程序(第3版)(完整版).pdf
操作系统——linux文件系统初实现——为fileSystem添加驱动,让linux可以识别。,布布扣,bubuko.com
时间: 2024-11-03 22:38:37