linux驱动程序学习笔记

字符型驱动

字符设备驱动结构

cdev结构体

用于完成描述一个字符设备。顶层。

  • 结构体定义
struct cdev {
 	struct kobject kobj; /* 内嵌的kobject对象 */
	struct module *owner; /* 所属模块*/
	struct file_operations *ops; /* 文件操作结构体*/
	struct list_head list;
	dev_t dev; /* 设备号*/
	unsigned int count;
};
  • cedv的操作
void cdev_init(struct cdev *, struct file_operations *);//初始化结构体
struct cdev *cdev_alloc(void);
void cdev_put(struct cdev *p);
int cdev_add(struct cdev *, dev_t, unsigned);//注册字符设备,通常在驱动加载模块中调用
void cdev_del(struct cdev *);//注销设备,通常在驱动卸载模块中调用

dev设备号

  1. 设备号定义与相互转换
    设备号为dev_t类型,32位,其中12位为主设备号(major),20位为次设备号(minor)。两者转换方法如下。
dev_t dev_num;
int dev_major,dev_minor;
//设备号到主次设备号,分离
dev_major=MAJOR(dev_num);
dev_minor=MINOR(dev_num);
//主次设备号到设备号,结合
dev_num=MKDEV(dev_major,dev_minor)
  1. 设备号分配与释放
  • 在调用cdev_add()函数向系统注册字符设备之前,应首先申请设备号。
    申请方式有两种:
register_chrdev_region(dev_t first,uint count,char *name);//(设备号起始值,设备个数,设备名)指定分配

alloc_chrdev_region(dev_t *dev_num,uint baseminor,uint count,char *name)//(用于接受分配设备号,次设备号起始值,设备个数,设备名)动态分配。
  • 在调用cdev_del()注销字符设备后,应释放申请的设备号。
unregister_chrdev_region(dev_t first, unsigned count);

file_operations结构体

file_operations结构体中的成员函数是字符设备驱动程序设计的主体内容,包括open()、write()、read()、close()等。
该结构体成员较多,因此这里只展示常用成员:

struct file_operations {
	struct module *owner; 
	int (*open) (struct inode *, struct file *);
	int (*release) (struct inode *, struct file *);
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

	unsigned int (*poll) (struct file *, struct poll_table_struct *);
	loff_t (*llseek) (struct file *, loff_t, int);//修改文件的当前读写位置
	int (*mmap) (struct file *, struct vm_area_struct *);
	

字符驱动程序框架

字符设备驱动程序设计框架
1.实现字符设备功能函数
基本功能函数:

static int char_device_open(struct inode *inode, struct file *filp);
static int char_device_release(struct inode *inode, struct file *filp);
static ssize_t char_device_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos);
static ssize_t char_device_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos);

2.定义和赋值file_operations结构
主要是以下7项:

static const struct file_operations char_device_fops={
    .owner = THIS_MODULE,
    .open = char_device_open,
    .release = char_device_release,
    .read = char_device_read,
    .write = char_device_write,
};

3.初始化设备
完成设备初始化需要完成设备号申请,字符设备结构初始化、字符设备添加。
a.设备号申请
设备号由dev_t 类型定义,12位主设备号(major)20位次设备号(minor),共32位。dev_t类型和int类型相互转化方法为:

dev_major=MAJOR(dev_num); dev_minor=MINOR(dev_num); //dev_t到int
dev_num=MKDEV(dev_major,dev_minor)//int到dev_t

设备号有两种申请方式:

register_chrdev_region(devno,1,"char_device");//指定主设备号申请
alloc_chrdev_region(&devno,0,1,"char_device");//内核分配主设备号申请

b. 字符设备结构初始化

cdev_init(&(char_device_devp->cdev),&globalmem_fops);

c.激活字符设备

cdev_add(&(char_device_devp->cdev),devno,1);
  1. 设备退出
    设备退出时,需要删除设备、释放设备号。
cdev_del(&globalmem_devp->cdev);
unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);

待归类知识点

内存申请函数

内存申请函数有:kmalloc()、kzalloc()、vmalloc() 。

  • kmalloc()
    申请的内存位于物理内存映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因为存在较简单的转换关系,所以对申请的内存大小有限制,不能超过128KB。分配过程是原子操作,不能被中断。对应释放函数kfree()。
  • kzalloc()
    与 kmalloc() 相似,参数及返回值是一样的,可以说是前者是后者的一个变种,因为 kzalloc() 实际上只是额外附加了 __GFP_ZERO 标志。所以它除了申请内核内存外,还会对申请到的内存内容清零。对应释放函数kfree()。
    -vmalloc()
    在虚拟内存空间给出一块连续的内存区,但这片连续的虚拟内存在物理内存中并不一定连续。由于 vmalloc() 没有保证申请到的是连续的物理内存,因此对申请的内存大小没有限制,如果需要申请较大的内存空间就需要用此函数了。vmalloc() 和 vfree() 可以睡眠,因此不能从中断上下文调用。对应释放函数vfree()。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值