简单字符设备驱动程序的操作步骤

本文介绍Linux驱动程序的开发流程,包括开发步骤、驱动框架及重要数据结构。详细讲解了如何利用file_operations结构来连接应用层API与驱动函数,并介绍了驱动程序的加载与卸载过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Linux驱动程序开发步骤

1.查看原理图,数据手册等

2.找相近的驱动程序作为模板

3.实现驱动程序的初始化

4.设计所要实现的操作:open,read,write,close

5.实现中断(可以不需要)

6.用insmod命令加载驱动


二、驱动框架

驱动是无法直接识别应用程序上的应用层API:read,open,write等,需要对应驱动程序上的led_read,led_open,led_write,这些都是驱动函数。

每个系统调用,驱动程序怎样和它对应起来?

使用file_operations结构,和应用层API对接。

Linux怎么知道去调用哪个驱动程序的file_operations?

根据设备类型和主设备号,需要将注册函数将主设备号和file_operations一起注册到内核

将驱动程序加载到内核,调用驱动初始化函数,像内核注册

module_init(memdev_init);


三、驱动程序的加载和卸载

module_init(memdev_init);

module_exit(memdev_exit);


 四、几种重要的数据结构

struct file

         file结构代表一个打开的文件,它由内核在open时创建,并传递给该文件上进行操作的所有函数,直到最后的close函数。

         file结构private_data是跨系统调用时保存状态信息非常有用的资源。

         file结构的f_ops 保存了文件的当前读写位置。

struct inode

         内核用inode代表一个磁盘上的文件,它和file结构不同,后者表示打开的文件描述符。对于单个文件,可能会有许多个表示打开文件的文件描述符file结构,但他们都指单个inode结构。inode的dev_t i_rdev成员包含了真正的设备编号,struct cdev *i_cdev包含了指向struct cdev结构的指针。

struct file_operations

         file_operations结构保存了字符设备驱动程序的方法。它是一个在 <linux/fs.h> 中定义的 struct file_operations 结构,这是一个内核结构,不会出现在用户空间的程序中,它定义了常见文件 I/O 函数的入口。系统调用函数通过内核,最终调用对应的 struct file_operations 结构的接口函数(例如,open() 文件操作是通过调用对应文件的file_operations 结构的 open 函数接口而被实现)。当然,每个设备的驱动程序不一定要实现其中所有的函数操作,若不需要定义实现时,则只需将其设为 NULL 即可。

驱动程序的简单模板:

#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");//模块开源许可声明

/* 模块加载时的初始化函数 */
// __init的意思是将代码放入特定的初始化内存区域,初始化后空间可以回收
static int __init myinit(void)
{
    printk(KERN_CRIT"hello mymodule!\n");
    printk(KERN_CRIT"module name :%s\n",THIS_MODULE->name);

    return 0;//内核编程,有返回值的一定不要遗漏
}
module_init(myinit);//告知系统哪个是初始化函数

/* 模块清理函数 */
//__exit的意思是如果以后不卸载则不要放入系统
static void __exit myexit(void)
{
    printk(KERN_CRIT"goodbye cruel world\n");
}
module_exit(myexit);//告知系统哪个是清理函数
设备号和设备类的创建和销毁:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h> //设备号注册相关
#include <linux/device.h> //class和device相关
MODULE_LICENSE("GPL");
dev_t devno;//设备号
struct class *cls; //设备类

static int __init myinit(void)
{//在模块初始化时,动态申请前设备号
    alloc_chrdev_region(&devno,10,1,"mydev");
    cls=class_create(THIS_MODULE,"myclass");//创建类
    device_create(cls,NULL,devno,NULL,"mynewdev");//在类下面创建设备
    printk("major is %d, minor is %d\n",MAJOR(devno),MINOR(devno));
    return 0;
}
module_init(myinit);
static void __exit myexit(void)
{//模块清理的时候,反注册设备号
    device_destroy(cls,devno);//销毁设备
    class_destroy(cls);//销毁类
    unregister_chrdev_region(devno,1);//反注册设备号
}
module_exit(myexit);












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值