Linux设备驱动开发之文件系统与设备开发

文件系统目录

随着linux内核的发展,其文件系统也在不断更新。下面我们看下我电脑目前使用的linux文件系统中根目录下的文件排布:
在这里插入图片描述
从上面我们可以看到当前的内核版本为4.15的该版本下的文件系统根目录下有很多文件。那么这些文件有哪些作用呢?我们来分析一下某些文件。

bin文件夹

这个文件夹包含基本命令,像ls、mkdir、cp等基本命令,都具有可执行属性。

sbin文件夹

这个文件夹包含了系统管理的命令,像modprobe、ifconfig等,都具有可执行属性。

dev文件夹

这个文件夹是设备文件的存储目录,应用程序通过对这些文件的读写和控制以访问实际的设备。

lib文件夹

这个文件夹存放的大都是系统的库文件。

mnt文件夹

这个文件夹一般用于存放挂载存储设备的挂载目录。

opt文件夹

这个文件夹是可选的意思,一般用户软件安装的位置就在这里。

proc文件夹

这个文件夹下是一个虚拟的文件系统。为什么说它是虚拟的?就是因为它的文件夹和文件不是存放在磁盘上的,是一直存放在内存中的,当内核结束时,该文件夹下的东西自动消失。这个虚拟文件系统记录了啥东西呢?它记录了操作系统运行时的进程及内核信息。我们可以通过访问这个文件夹知道此时操作系统发生了什么。

tmp文件夹

这个文件夹是用来存放临时文件的。

usr文件夹

这个文件夹是用来存放系统程序的,比如用户命令、用户库等。

var文件夹

这个文件夹里的内容经常变动,比如/var/log就是用来存放系统日志的目录。

sys文件夹

这个文件夹就有意思了,它里面是一个虚拟的文件系统。跟proc一样的,最初sys里面的内容就是从proc里拆离出来的。这个虚拟文件系统就是sysfs文件系统。linux设备驱动模型中总线、驱动和设备都可以在该文件系统中找到对应的节点。

文件系统与设备驱动

文件系统与设备驱动啥关系呢?首先我们先讨论一下什么是文件系统?其实文件系统就是存储设备组织文件的方法。能够掉电存储的设备上的组织文件方法我们称为实际的文件系统;只能在电情况下存储设备的组织方法我们称为虚拟的文件系统,因为掉电这个组织方法就不存在这个存储设备上了。像ext2、ext3、fat等等这么多种类的文件系统,都是有各自一套对存储设备文件的组织方法,使用这些组织方法可以让我们更方便使用存储设备上的文件,不然一大堆的二进制文件会看得脑壳疼。。。。
那么设备驱动又是啥呢?对于代码来说,简而言之,配置设备驱动就是那配置那一个个寄存器位,使得设备按照我们的预想工作。为了使用方便,在内核中定义了设备的结构体file_operations,配置设备驱动时,可以配置这个file_operations结构体中的变量或者方法。
那么二者有啥关系呢?我们一般配置某个设备的驱动代码时,是不会直接调用file_operations中的方法的,因为使用这个结构体太麻烦了。这时,我们会封装一层文件系统接口,然后当我们使用那个设备时,直接使用那个文件系统接口就可以了。当然了,这个文件系统就是虚拟的,它只是为了方便统一操作设备驱动,还有真实的文件系统,以及一些特殊文件等。我们可以看下文件系统与设备驱动的图:
在这里插入图片描述
在驱动程序设计中,比较重要的是这2个结构体file结构体、inode结构体。下面我们来讨论一下它们。

file结构体

// include/linux/fs.h 
struct file {
 801         union {
 802                 struct llist_node       fu_llist;
 803                 struct rcu_head         fu_rcuhead;
 804         } f_u;
 805         struct path             f_path;
 806         struct inode            *f_inode;       /* cached value */
 807         const struct file_operations    *f_op;
 808 
 809         /*
 810          * Protects f_ep_links, f_flags.
 811          * Must not be taken from IRQ context.
 812          */
 813         spinlock_t              f_lock;
 814         atomic_long_t           f_count;
 815         unsigned int            f_flags;
 816         fmode_t                 f_mode;
 817         struct mutex            f_pos_lock;
 818         loff_t                  f_pos;
 819         struct fown_struct      f_owner;
 820         const struct cred       *f_cred;
 821         struct file_ra_state    f_ra;
 822 
 823         u64                     f_version;
 824 #ifdef CONFIG_SECURITY
 825         void                    *f_security;
 826 #endif
 827         /* needed for tty driver, and maybe others */
 828         void                    *private_data;
 829 
 830 #ifdef CONFIG_EPOLL
 831         /* Used by fs/eventpoll.c to link all the hooks to this file      */
 832         struct list_head        f_ep_links;
 833         struct list_head        f_tfile_llink;
 834 #endif /* #ifdef CONFIG_EPOLL */
 835         struct address_space    *f_mapping;
 836 } __attribute__((aligned(4)));  /* lest something weird decides that     2 is OK */

file结构体代表一个打开的文件,系统中每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。

这个file结构体中保存了这么成员,其中文件的私有数据成员会被大量用到,用来携带处理接口的。

inode结构体

// include/linux/fs.h 
struct inode {
 556         umode_t                 i_mode;
 557         unsigned short          i_opflags;
 558         kuid_t                  i_uid;
 559         kgid_t                  i_gid;
 560         unsigned int            i_flags;
 561 
 562 #ifdef CONFIG_FS_POSIX_ACL
 563         struct posix_acl        *i_acl;
 564         struct posix_acl        *i_default_acl;
 565 #endif
 566 
 567         const struct inode_operations   *i_op;
 568         struct super_block      *i_sb;
 569         struct address_space    *i_mapping;
 570 
 571 #ifdef CONFIG_SECURITY
 572         void                    *i_security;
 573 #endif
 574 
 575         /* Stat data, not accessed from path walking */
  576         unsigned long           i_ino;
 577         /*
 578          * Filesystems may only read i_nlink directly.  They shall us     e the
 579          * following functions for modification:
 580          *
 581          *    (set|clear|inc|drop)_nlink
 582          *    inode_(inc|dec)_link_count
 583          */
 584         union {
 585                 const unsigned int i_nlink;
 586                 unsigned int __i_nlink;
 587         };
 588         dev_t                   i_rdev;
 589         loff_t                  i_size;
 590         struct timespec         i_atime;
 591         struct timespec         i_mtime;
 592         struct timespec         i_ctime;
 593         spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i     _size */
 594         unsigned short          i_bytes;
 595         unsigned int            i_blkbits;
 596         blkcnt_t                i_blocks;
 597 
 598 #ifdef __NEED_I_SIZE_ORDERED
 599         seqcount_t              i_size_seqcount;
 600 #endif
 601 
 602         /* Misc */
 603         unsigned long           i_state;
 604         struct mutex            i_mutex;
 605 
 606         unsigned long           dirtied_when;   /* jiffies of first d     irtying */
 607 
 608         struct hlist_node       i_hash;
 609         struct list_head        i_wb_list;      /* backing dev IO lis     t */
 610         struct list_head        i_lru;          /* inode LRU list */
 611         struct list_head        i_sb_list;
 612         union {
 613                 struct hlist_head       i_dentry;
 614                 struct rcu_head         i_rcu;
 615         };
 616         u64                     i_version;
 617         atomic_t                i_count;
 618         atomic_t                i_dio_count;
 619         atomic_t                i_writecount;
 620 #ifdef CONFIG_IMA
 621         atomic_t                i_readcount; /* struct files open RO      */
 622 #endif
 623         const struct file_operations    *i_fop; /* former ->i_op->def     ault_file_ops */
 624         struct file_lock_context        *i_flctx;
 625         struct address_space    i_data;
 626         struct list_head        i_devices;
 627         union {
 628                 struct pipe_inode_info  *i_pipe;
 629                 struct block_device     *i_bdev;
 630                 struct cdev             *i_cdev;
 631         };
 632 
 633         __u32                   i_generation;
 634 
 635 #ifdef CONFIG_FSNOTIFY
 636         __u32                   i_fsnotify_mask; /* all events this i     node cares about */
 637         struct hlist_head       i_fsnotify_marks;
 638 #endif
 639 
 640         void                    *i_private; /* fs or device private p     ointer */
 641 };

这个inode结构体记录了一个文件访问权限、属主、组、大小、生成时间、访问时间、最后修改时间以及在设备上的存储块等信息。对于表示设备文件的inode结构,i_rdev字段包含设备编号。Linux内核设备编号分为主设备编号和次设备编号,前者为dev_t的高12位,后者为dev_t的低20位。
查看/proc/devices可以知道系统中目前已经注册的设备。第一列为主设备号,第二列为设备名。
查看/dev目录可以获知系统中包含的设备文件。内核Documents目录下的devices.txt文件描述了Linux设备号的分配情况。

总结

详情请参考宋宝华老师的书。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值