Linux内核模块和Linux fs 与 sysfs 一

 注: 参考整理自《Linux设备驱动开发详解》

 

一 Linux 内核模块 :

    1. 查找系统中加载的模块: lsmod ; 卸载模块命令 : rmmod ;  装载命令: insmod/modprobe(modprobe 会自动分析模块间的依赖关系);

    2. 模块加载函数:利用__init 标识

             static int __init  ***_init(void)

             {

                   ................

              }

              module_init(***_init);

            返回0表示加载成功, 失败则返回一些错误代码,参考<linux/errno.h>

           在加载函数中一般用于初始化硬件,申请资源.....

    3. 模块卸载函数:利用__exit标识

            static void __exit ***_exit(void)

            {

                  .............

            }

            module_exit(***_exit);

      注: 在卸载模块的函数中,一般需要完成以下的几件事情:

          # 若模块加载函数中注册了***,则在模块卸载函数中需注销;

          # 若在模块加载函数中动态申请了内存,则在此亦需要释放;

          # 若在模块加载中申请了一些硬件资源(如:IRQ, DMA channel, I/O ,memory),则在此需释放;

    4. 模块参数 : module_param(参数名, 参数类型, 参数读/写权限)

           注: 可以利用上述的方法在加载模块时传递需要的参数。

     5. 导出符号 : 记录了该符号以及该符号所在的内存地址。

           可以使用:

                          EXPORT_SYMBOL(符号名);

                          EXPORT_SYMBOL_GPL(符号名);

           该功能在内核中使用较多,只要导出该符号,则其他的模块在调用该符号时,只需声明则可;这有点类似于跨文件的函数间调用。

     6. 模块声明与描述:

          MODULE_AUTHOR(author);

          MODULE_DESCRIPTION(description);

          MODULE_VERSION(version_string);

          MODULE_DEVICE_TABLE(table_info);

          MODULE_ALIAS(alternate_name);

     7.  模块的编译 :

           下面演示一个 Makefile :

       #Makefile for wm8350_rtc
        obj-m           := wm8350_rtc.o

        all:
                     make -C ../../../linux-2.6.26 M=`pwd` modules

       clean:
                     make -C ../../../linux-2.6.26 M=`pwd` clean
                     rm -f modules.orde

        分析: -C 表示Linux内核所在的目录,需注意的是,这个目录是之前设置好的用来编译zImage的源码;

                  M 表示指定的需要编译成模块的代码源文件和Makefile 文件;

                  modules ----表示编译为内核模块。

 

二, Linux文件系统:

       1. C中的文件操作: open , write, read, close,

       2.在Linux的驱动开发中,需要关注的是如下两个结构:

            1) file_operations :应用程序和 VFS(virtual FS)之间通过系统调用链接,而VFS 和普通设备之间则通过file_operation的成员函数(如: read ,write, open ,close ,ioctl ...)

             file 结构体 :参考: /linux/include/linux/fs.h:

               struct file { /* * fu_list becomes invalid after file_free is called and queued via * fu_rcuhead for RCU freeing */ union { struct list_head fu_list; struct rcu_head fu_rcuhead; } f_u; struct path f_path; #define f_dentry f_path.dentry #define f_vfsmnt f_path.mnt const struct file_operations *f_op; atomic_t f_count; unsigned int f_flags; mode_t f_mode; loff_t f_pos; struct fown_struct f_owner; unsigned int f_uid, f_gid; struct file_ra_state f_ra; u64 f_version; #ifdef CONFIG_SECURITY void *f_security; #endif /* needed for tty driver, and maybe others */ void *private_data; #ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_head f_ep_links; spinlock_t f_ep_lock; #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; #ifdef CONFIG_DEBUG_WRITECOUNT unsigned long f_mnt_write_state; #endif };

        另外可以参考一下 file_operation 的描述:

         struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*dir_notify)(struct file *filp, unsigned long arg); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **); }

             2) inode : 包括文件访问权限,属主,组,大小,生成时间,访问时间,最后修改时间等...

                     inode的结构体定义也是在include/linux/fs.h

         3. ps: 可以使用 cat /proc/devices 查询系统中注册的设备。

 

三, sysfs  --- Linux驱动开发使用得较多,尤其是需要显示一些设备的信息时,而且Android中,sysfs的使用也很多。

         1. 目的: sysfs 显示设备驱动模型中各个模块间的层次关系: ls /sys ---可以看到其顶级目录 包括 :

                      block  bus  class  devices  firmware  module  power

              其中: block ----显示块设备;

                         bus   ----显示系统中所有的总线;

                         class ----显示系统中的设备类型;

                         device --显示系统中所有的设备并根据设备挂接的总线类型组织成层次关系;

                         drivers ---包括内核中所有已注册的设备驱动程序;

 

你可能感兴趣的:(linux,struct,File,Module,makefile,linux内核)