操作系统——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*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);
View Code

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
View Code

5、配置命令:

1)创建Makefile文件:

2)执行make命令:
root@mmc-vm:/usr/mmc/dirPro/charDri# make

3)将生成的驱动模块插入内核:
root@mmc-vm:/usr/mmc/dirPro/charDri# insmod ./chardev.ko

4)查看插入后的情况:
root@mmc-vm:/usr/mmc/dirPro/charDri# lsmod

5)设备节点的创建:
root@mmc-vm:/usr/mmc/dirPro/charDri# mknod /dev/chardev0 c 250 0

6)编译用户程序gcc -o chardev_test main.c
root@mmc-vm:/usr/mmc/dirPro/charDri# gcc -o test test.c -std=c99

7)运行chmod 666 /dev/chardev0 使其它用户也可以对这个设备进行读写操作,否则只有root用户可以对它进行读写。
root@mmc-vm:/usr/mmc/dirPro/charDri# chmod 666 /dev/chardev0

8)运行test
root@mmc-vm:/usr/mmc/dirPro/charDri# ./test

9)删除设备节点,就像删除普通文件一样:
root@mmc-vm:/usr/mmc/dirPro/charDri# rm /dev/chardev0


10)卸载内核驱动模块
root@mmc-vm:/usr/mmc/dirPro/charDri# rmmod chardev.ko

11)重新运行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

操作系统——linux文件系统初实现——为fileSystem添加驱动,让linux可以识别。,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。