回顾
装载模块到正运行的内核和移除模块
#include<linux/ini.h>
module_init();
module_exit();
用于指定模块的初始化和清除函数的宏
__init
__exit
__initdata
__exitdata
#include<linux/sched.h>
最重要的头文件之一,该文件包含驱动程序使用的大部分内核api函数的定义,包含睡眠函数以及各种变量声明。
struct task_current *current;//当前进程
current->pid //进程id
current->comm //命令名
#include<linux/version.h>
内核版本信息
#include<linux/module.h>
必须 的头文件,必须包含在模块源代码中
#include<linux/moduleparam.h>
模块参数
module_param(variable,type,perm);
#include<linux/kernel.h>
int printk(const char * fmt,...)
container_of(pointer, type, field)
一个方便使用的宏,它用于从包含在某个结构中的指针获得结构本身的指针
#include<linux/fs.h>
文件系统头文件,它是编写设备驱动程序的必需的头文件
int register_chrdev_region(dev_t first, unsigned int count, char *name)
first 是要分配的设备编号范围的起始值,first的次设备号经常被设为0,但对函数来将并不是必须的,count 是所请求的连续设备编号的个数,常设为1,如果count非常大,那请求的范围内可能和下一个主设备重迭,name是和该编号范围关联的设备名称,他讲出现在sysfs中
和大部分内核函数一样,register_chrdev_region返回值在分配成功时为0,错误情况下返回一个负的错误码,
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
dev为输出的参数,firstminor是要使用的被请求的第一个次设备号,通常是0,count 与name 同上
void unregister_chrdev_region(dev_t first, unsigned int count);
#include<linux/cdev.h>
初始化、注册字符设备
void cdev_init(cdev *cdev, struct file_operations *fops);
初始化分配到的结构
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
告诉内核该cdev结构的信息
void cdev_del(struct cdev *dev)
#include<linux/types.h>
dev_t 表示设备编号的数据类型
int MAJOR(dev_t dev)
int MINOR(dev_t dev)
获取主次编号
dev_t MKDEV(unsigned int major, unsigned int minor)
由主次编号构造dev_t数据项
struct file_operations;
struct file;
struct inode;
大多数设备驱动都会用到的三个数据结构,
file_operations结构保存字符设备驱动程序的方法
file结构表示一个打开的文件
inode结构表示磁盘上的文件
#include<asm/uaccess.h>
内核代码和用户空间之间移动数据的函数
unsigned long copy_from_user(void *to, const void *from, unsigned long count);
unsigned long copy_to_user(void *to, const void *from, unsigned long count);