首页 > 代码库 > 操作系统——linux文件系统初实现——为fileSystem添加驱动,让linux可以识别。

操作系统——linux文件系统初实现——为fileSystem添加驱动,让linux可以识别。

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*500static 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);
View Code

4、Makefile:

ifneq ($(KERNELRELEASE),)obj-m := chardev.oelseKERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default:    $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesendif
View Code

5、配置命令:

1)创建Makefile文件:2)执行make命令:root@mmc-vm:/usr/mmc/dirPro/charDri# make3)将生成的驱动模块插入内核:root@mmc-vm:/usr/mmc/dirPro/charDri# insmod ./chardev.ko4)查看插入后的情况:root@mmc-vm:/usr/mmc/dirPro/charDri# lsmod5)设备节点的创建:root@mmc-vm:/usr/mmc/dirPro/charDri# mknod /dev/chardev0 c 250 06)编译用户程序gcc -o chardev_test main.croot@mmc-vm:/usr/mmc/dirPro/charDri# gcc -o test test.c -std=c997)运行chmod 666 /dev/chardev0 使其它用户也可以对这个设备进行读写操作,否则只有root用户可以对它进行读写。root@mmc-vm:/usr/mmc/dirPro/charDri# chmod 666 /dev/chardev08)运行testroot@mmc-vm:/usr/mmc/dirPro/charDri# ./test9)删除设备节点,就像删除普通文件一样:root@mmc-vm:/usr/mmc/dirPro/charDri# rm /dev/chardev010)卸载内核驱动模块root@mmc-vm:/usr/mmc/dirPro/charDri# rmmod chardev.ko11)重新运行test,观察结果12)重新插入内核驱动模块和设备节点,又可以正常显示结果
View Code

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