当前位置:首页 > > IOT物联网小镇
[导读]作 者:道哥,10年嵌入式开发老兵,专注于:C/C、嵌入式、Linux。关注下方公众号,回复【书籍】,获取Linux、嵌入式领域经典书籍;回复【PDF】,获取所有原创文章(PDF格式)。目录混乱的API函数旧的API函数新的API函数代码实操创建驱动程序源文件创建Makefile...

作  者:道哥,10 年嵌入式开发老兵,专注于:C/C 、嵌入式、Linux


关注下方公众号,回复【书籍】,获取 Linux、嵌入式领域经典书籍;回复【PDF】,获取所有原创文章( PDF 格式)。


目录


  • 混乱的 API 函数


  • 旧的 API 函数


  • 新的 API 函数


  • 代码实操


    • 创建驱动程序源文件


    • 创建 Makefile 文件


    • 编译、加载驱动模块


  • 应用程序


    • 打开、读取、写入设备


    • 卸载驱动模块


    • 小结


  • 自动在 /dev 目录下创建设备节点


  • 代码下载


别人的经验,我们的阶梯!


大家好,我是道哥,今天我为大伙儿解说的技术知识点是:【字符设备的驱动程序】


在上一篇文章中,讨论的是Linux系统中,驱动模块的两种编译方式。


我们就继续以此为基础,用保姆级的粒度一步一步操作,来讨论一下字符设备驱动程序的编写方法。


  1. 这篇文章的实际操作部分,使用的是的 API 函数;


  2. 下一篇文章,再来演示新的 API 函数;


混乱的 API 函数

我在刚开始接触Linux驱动的时候,非常的困扰:注册一个字符设备,怎么有这么多的 API 函数啊?


参考的每一篇文章中,使用的函数都不一样,但是执行结果都是符合预期的!


比如下面这几个:


  1. register_chrdev(...);


  2. register_chrdev_regin(...);


  3. cdev_add(...);


它们的功能都是向系统注册字符设备,但是只从函数名上看,初学者谁能分得清它们的区别?!


这也难怪,Linux系统经过这么多年的发展,代码更新是很正常的事情。


但是,我们参考的文章就没法做到:很详细的把文章中所描述内容的背景介绍清楚,往往都是文章作者在自己的实际工作环境中,测试某种方法解决了自己的问题,于是就记录成文。


不同的文章、不同的工作上下文、不同的API函数调用,这往往就苦了我们初学者,特别是我这种有选择障碍症的人!


其实,上面这个几个函数都是正确的,它们的功能都是类似的,它们是Linux系统中不同阶段的产物。


旧的 API 函数

在Linux内核代码2.4版本和早期的2.6版本中,注册、卸载字符设备驱动程序的经典方式是:


注册设备:


int register_chrdev(unsigned int major,const char *name,struct file_operations *fops);
参数1 major:如果为0 - 由操作系统动态分配一个主设备号给这个设备;如果非0 - 驱动程序向系统申请,使用这个主设备号;


参数2 name:设备名称;


参数3 fops:file_operations 类型的指针变量,用于操作设备;


如果是动态分配,那么这个函数的返回值就是:操作系统动态分配给这个设备的主设备号。


这个动态分配的设备号,我们要把它记住,因为在其他的API函数中需要使用它。


卸载设备:


int unregister_chrdev(unsigned int major,const char *name)
参数1 major:设备的主设备号,也就是 register_chrdev() 函数的返回值(动态),或者驱动程序指定的设备号(静态方式);


参数2 name:设备名称;


新的 API 函数

注册设备:


int register_chrdev_region(dev_t from, unsigned count, const char *name);
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);
上面这2个注册设备的函数,其实对应着旧的 API 函数 register_chrdev:把参数 1 表示的动态分配、静态分配,拆分成2个函数而已。


也就是说:


register_chrdev_region(): 静态注册设备;


alloc_chrdev_region(): 动态注册设备;


这两个函数的参数含义是:


register_chrdev_region参数:


参数1 from: 注册指定的设备号,这是静态指定的,例如:MKDEV(200, 0) 表示起始主设备号 200, 起始次设备号为 0;


参数2 count: 驱动程序指定连续注册的次设备号的个数,例如:起始次设备号是 0,count 为 10,表示驱动程序将会使用 0 ~ 9 这 10 个次设备号;


参数3 name:设备名称;


alloc_chrdev_region参数:


参数1 dev: 动态注册就是系统来分配设备号,那么驱动程序就要提供一个指针变量来接收系统分配的结果(设备号);


参数2 baseminor: 驱动程序指定此设备号的起始值;


参数3 count: 驱动程序指定连续注册的次设备号的个数,例如:起始次设备号是 0,count 为 10,表示驱动程序将会使用 0 ~ 9 这 10 个次设备号;


参数4 name:设备名称;


补充一下关于设备号的内容:


这里的结构体dev_t,用来保存设备号,包括设备号和设备号。


它本质上是一个32位的数,其中的12位用来表示设备号,而其余20位用来表示设备号。


系统中定义了3宏,来实现dev_t变量、主设备号、次设备号之间的转换:


MAJOR(dev_t dev): 从  dev_t 类型中获取主设备号;


MINOR(dev_t dev):  从 dev_t 类型中获取次设备号;


MKDEV(int major,int minor): 把主设备号和次设备号转换为 dev_t 类型;


卸载设备:


void unregister_chrdev_region(dev_t from, unsigned count);
参数1 from: 注销的设备号;


参数2 count: 注销的连续次设备号的个数;


代码实操

下面,我们就用旧的API函数,一步一步的描述字符设备驱动程序的:编写、加载和卸载过程


如何使用新的API函数来编写字符设备驱动程序,下一篇文章再详细讨论。


以下所有操作的工作目录,都是与上一篇文章相同的,即:~/tmp/linux-4.15/drivers/。


创建驱动目录和驱动程序

$ cd linux-4.15/drivers/
$ mkdir my_driver1
$ cd my_driver1
$ touch driver1.c
driver1.c文件的内容如下(不需要手敲,文末有代码下载链接):


#include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include


  • static unsigned int major;

    int driver1_open(struct inode *inode, struct file *file)
    {
    printk("driver1_open is called. \n");
    return 0;
    }

    ssize_t driver1_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
    {
    printk("driver1_read is called. \n");
    return 0;
    }

    ssize_t driver1_write (struct file *file, const char __user *buf, size_t size, loff_t *ppos)
    {
    printk("driver1_write is called. \n");
    return 0;
    }

    static const struct file_operations driver1_ops={
    .owner = THIS_MODULE,
    .open = driver1_open,
    .read = driver1_read,
    .write = driver1_write,
    };

    static int __init driver1_init(void)
    {
    printk("driver1_init is called. \n");

    major = register_chrdev(0, "driver1",
  • 本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
    换一批
    延伸阅读

    特朗普集团近日取消了其新推出的T1智能手机“将在美国制造”的宣传标语,此举源于外界对这款手机能否以当前定价在美国本土生产的质疑。

    关键字: 特朗普 苹果 AI

    美国总统特朗普在公开场合表示,他已要求苹果公司CEO蒂姆·库克停止在印度建厂,矛头直指该公司生产多元化的计划。

    关键字: 特朗普 苹果 AI

    4月10日消息,据媒体报道,美国总统特朗普宣布,美国对部分贸易伙伴暂停90天执行新关税政策,同时对中国的关税提高到125%,该消息公布后苹果股价飙升了15%。这次反弹使苹果市值增加了4000多亿美元,目前苹果市值接近3万...

    关键字: 特朗普 AI 人工智能 特斯拉

    3月25日消息,据报道,当地时间3月20日,美国总统特朗普在社交媒体平台“真实社交”上发文写道:“那些被抓到破坏特斯拉的人,将有很大可能被判入狱长达20年,这包括资助(破坏特斯拉汽车)者,我们正在寻找你。”

    关键字: 特朗普 AI 人工智能 特斯拉

    1月22日消息,刚刚,新任美国总统特朗普放出重磅消息,将全力支持美国AI发展。

    关键字: 特朗普 AI 人工智能

    特朗普先生有两件事一定会载入史册,一个是筑墙,一个是挖坑。在美墨边境筑墙的口号确保边境安全,降低因非法移民引起的犯罪率过高问题;在中美科技产业之间挖坑的口号也是安全,美国企业不得使用对美国国家安全构成威胁的电信设备,总统...

    关键字: 特朗普 孤立主义 科技产业

    据路透社1月17日消息显示,知情人士透露,特朗普已通知英特尔、铠侠在内的几家华为供应商,将要撤销其对华为的出货的部分许可证,同时将拒绝其他数十个向华为供货的申请。据透露,共有4家公司的8份许可被撤销。另外,相关公司收到撤...

    关键字: 华为 芯片 特朗普

    曾在2018年时被美国总统特朗普称作“世界第八奇迹”的富士康集团在美国威斯康星州投资建设的LCD显示屏工厂项目,如今却因为富士康将项目大幅缩水并拒绝签订新的合同而陷入了僵局。这也导致富士康无法从当地政府那里获得约40亿美...

    关键字: 特朗普 富士康

    今年5月,因自己发布的推文被贴上“无确凿依据”标签而与推特发生激烈争执后,美国总统特朗普签署了一项行政令,下令要求重审《通信规范法》第230条。

    关键字: 谷歌 facebook 特朗普

    众所周知,寄往白宫的所有邮件在到达白宫之前都会在他地进行分类和筛选。9月19日,根据美国相关执法官员的通报,本周早些时候,执法人员截获了一个寄给特朗普总统的包裹,该包裹内包含蓖麻毒蛋白。

    关键字: 美国 白宫 特朗普
    关闭