字符设备驱动基本框架详解、注册设备号、添加字符设备、以及注销删除设备


前言

时隔很久,我又来开始更新驱动模块的学习了,希望在我学习的过程中,能够把自己遇到的问题和干货分享给大家,如果遇到问题,恳请大家评论区及时订正!


一、字符设备驱动框架基本解析

以下将通过一个具体的例子来分析字符设备驱动的基本框架:
功能:实现打开设备、关闭设备的基本驱动操作

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>

int major = 11; 		//主设备号
int minor = 0; 			//次设备号
int mychar_num = 1; 	//设备数量

struct cdev mydev; 		//每一类设备都有一个cdev结构体
int mychar_open(struct inode *pnode, struct file *pfile)
{
	printk("mychar open is called!!!\n");
	return 0;
}

int mychar_close(struct inode *pnode, struct file *pfile)
{

	printk("mychar clsoe is called!!!\n");
	return 0;
}

/* 对字符设备的操作函数 */
struct file_operations myops = {
	.owner = THIS_MODULE,
	.open = mychar_open,
	.release = mychar_close,
};

int __init mychar_init(void)
{
	int ret = 0;

	dev_t devno = MKDEV(major, minor); 										//组合设备号

	ret = register_chrdev_region(devno, mychar_num, "mychar"); 				//手动申请设备号
	if (ret) 																//返回值为0表示申请成功
	{
		ret = alloc_chrdev_region(&devno, 0, mychar_num, "mychar"); 	//申请失败则系统自动分配
		if (ret)
		{
			printk("get devno failed!\n");
			return -1;
		}
		major = MAJOR(devno); 												//从系统分配的设备号中取出主设备号
		minor = MINOR(devno); 												//从系统分配的设备号中取出次设备号
		devno = MKDEV(major, minor); 										//组合设备号
	}

	/* 使得设备具有myops中的函数操作方法 */
	cdev_init(&mydev, &myops);
	mydev.owner = THIS_MODULE;		//表示mydev设备属于此内核模块

	/* 将设备号为devno的这个设备(mydev)添加到内核(内核hash链表中) */
	cdev_add(&mydev, devno, mychar_num);


	printk("hello world!\n");
	return 0;
}

void __exit mychar_exit(void)
{
	dev_t devno = MKDEV(major, minor); 					//组合设备号
	
	unregister_chrdev_region(devno, mychar_num); 		//注销设备号

	/* 从内核中删除mydev这个设备 */
	cdev_del(&mydev);
	printk("bye bye!!!\n");
}

MODULE_LICENSE("GPL");
module_init(mychar_init);
module_exit(mychar_exit);

收获:1.在字符设备驱动程序中,每个设备都有主设备号和次设备号,主设备号表示一类设备,
次设备号可以表示这一类设备中具体的某个设备
2.每一类设备都有一个struct cdev类型的结构体来表示这类设备
3.应用层中通过系统调用来访问驱动函数,其中两个重要的结构体分别是

 (1)struct inode *pnode:作用为链接设备号,关联字符设备的操作函数集
 (2)struct file *pfile :作用为记录文件标识符的位置,传递本次打开文件的私有数据等等

4.struct file_operations myops:表示驱动所支持的函数操作集合
5.编写字符设备驱动的基本顺序:

(1)必须有主设备号,次设备号和设备数量,可以手动申请注册设备号register_chrdev_region或者系统自动分配设备号alloc_chrdev_region,MKDEV可以将主设备号和次设备号组合成设备号
(2)框架中需要涉及到驱动模块入口函数(对字符设备进行cdev_init初始化,添加字符设备cdev_add)*	和驱动模块出口函数(注销设备号unregister_chrdev_region,从内核中删除设备cdev_del)
(3)module_init(mychar_init); module_exit(mychar_exit);指定入口函数和出口函数

二、 应用层

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>


int main(int argc, const char *argv[])
{
	int fd = -1;

	if (argc < 2)
	{
		printf("the arguement is too few!\n");
		return -1;
	}

	fd = open(argv[1], O_RDONLY);
	if(fd < 0)
	{
		printf("fail to open %s\n", argv[1]);
		return -1;
	}

	close(fd);
	fd = -1;

	return 0;
}

应用层程序,对字符设备进行打开操作,以此可以调用驱动程序中的mychar_read函数;


总结

本文主要分享的分两个部分,一个是驱动程序,另一个是应用程序,主要介绍驱动程序的基本框架。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值