关于字符驱动中的变量,宏,头文件等的简介 module_init module_exit

ssize_t second_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { }

这是一个文件读函数 

ssize_t是signed size_t,
size_t是标准C库中定义的,应为unsigned int。
我们很容易看出输入参数中 
file 是文件 
buf 是文件要读到什么地方去,用户buf 
count是要读多少东西 

那么ppos是什么东东,是当前文件的偏移量嘛?? 
但是当前文件的偏移量在filp中有定义呀。struct file { 
struct list_head f_list; 
struct dentry *f_dentry; 
struct vfsmount *f_vfsmnt; 
struct file_operations *f_op; 
atomic_t f_count; 
unsigned int f_flags; 
mode_t f_mode; 
loff_t f_pos;//这个就是当前文件的偏移量,

struct file 中的f_pos是最后一次文件操作以后的当前读写位置。而ppos是这次对文件进行操作的起始位置,这两个值不一定相等

module_init module_exit

像你写C程序需要包含C库的头文件那样,Linux内核编程也需要包含Kernel头文件,大多的Linux驱动程序需要包含下面三个头文件:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
    其中,init.h 定义了驱动的初始化和退出相关的函数,kernel.h 定义了经常用到的函数原型及宏定义,module.h 定义了内核模块相关的函数、变量及宏。

几乎每个linux驱动都有个module_init(与module_exit的定义在Init.h (\include\linux) 中)。驱动的加载就靠它。

module_init除了初始化加载之外,还有后期释放内存的作用。linux kernel中有很大一部分代码是设备驱动代码,这些驱动代码都有初始化和反初始化函数,这些代码     linux就是这样做的,对只需要初始化运行一次的函数都加上__init属性,__init 宏告诉编译器如果这个模块被编译到内核则把这个函数放到(.init.text)段,module_exit的参数卸载时同__init类似,如果驱动被编译进内核,则__exit宏会忽略清理函数,因为编译进内核的模块不需要做清理工作,显然__init和__exit对动态加载的模块是无效的,只支持完全编译进内核。

像你写C程序需要包含C库的头文件那样,Linux内核编程也需要包含Kernel头文件,大多的Linux驱动程序需要包含下面三个头文件:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
    其中,init.h 定义了驱动的初始化和退出相关的函数,kernel.h 定义了经常用到的函数原型及宏定义,module.h 定义了内核模块相关的函数、变量及宏。

几乎每个linux驱动都有个module_init(与module_exit的定义在Init.h (\include\linux) 中)。驱动的加载就靠它。

module_init除了初始化加载之外,还有后期释放内存的作用。linux kernel中有很大一部分代码是设备驱动代码,这些驱动代码都有初始化和反初始化函数,这些代码     linux就是这样做的,对只需要初始化运行一次的函数都加上__init属性,__init 宏告诉编译器如果这个模块被编译到内核则把这个函数放到(.init.text)段,module_exit的参数卸载时同__init类似,如果驱动被编译进内核,则__exit宏会忽略清理函数,因为编译进内核的模块不需要做清理工作,显然__init和__exit对动态加载的模块是无效的,只支持完全编译进内核。

猜你喜欢

转载自www.cnblogs.com/y4247464/p/10087621.html