字符设备驱动

来源:互联网 发布:淘宝店铺装修计划 编辑:程序博客网 时间:2024/06/04 01:39

Linux内核分析(五)

昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷,我们都会以虚拟的设备为例进行学习,所以大家不必害怕没有硬件的问题。

今天我们会分析到以下内容:

1.      字符设备驱动基础

2.      简单字符设备驱动实现

3.      驱动测试

 

l  字符设备基础

1.       字符设备描述结构

在linux2.6内核中,使用cdev结构体描述一个字符设备,其定义如下:

 

复制代码
1 struct cdev {2     struct kobject kobj;/*基于kobject*/3     struct module *owner; /*所属模块*/4     const struct file_operations *ops; /*设备文件操作函数集*/5     struct list_head list; 6     dev_t dev; /*设备号*/7     unsigned int count; /*该种类型设备数目*/8 };
复制代码

上面结构中需要我们进行初始化的有ops和dev,下面我们会对这两个成员进行分析。

注:kobject结构是驱动中很重要的一个结构,由于其复杂性,我们现在不进行介绍,后面会详细介绍。

2.       设备号

1.        何为设备号:cdev结构体中dev成员定义了设备号,而dev_t则为U32类型的也就是32位,其中12位为主设备号,20位为次设备号。我们执行ls –l /dev/可看到下图,其中左边红框为主设备号,右边为次设备号

2.        何为主设备号:用来对应该设备为何种类型设备。(比如串口我们用一个数字识别,而串口有好几个)

3.        何为次设备号:用来对应同一类型设备下的具体设备。(用次设备号来具体区分是哪个串口)

4.        设备号相关操作:

1.        通过主设备号和次设备号获取dev:dev = MKDEV(主,次);

2.        通过dev获取主设备号:主 = MAJOR(dev);

3.        通过dev获取次设备号:dev = MINOR(dev);

5.        设备号分配:设备号的分配有两种方式,一种是静态的,另一种是动态的,下面一一分析

1.        静态分配:也就是程序员自己指定设备号,通过register_chrdev_region();函数向内核申请,可能会导致和内核已有的冲突,从而失败。

2.        动态分配:通过 alloc_chrdev_region(); 函数向内核申请设备号。

3.        释放设备号:通过 unregister_chrdev_region(); 释放申请到的设备号。

3.       file_operations操作函数集

file_operations结构体中的成员函数在我们驱动开发过程中极为重要,其中的内容相当庞大,下面我们看看其定义:

 

 View Code

上面结构体中的函数指针所指向的函数,在我们在进行open、write、read等系统调用的时候最终会被调用到,所以我们的驱动中想为应用层实现那种调用就要在此实现。

4.       字符设备驱动初始化

我们通过上面的分析对设备号和操作函数集有了一定的了解下面我们来看字符设备驱动初始化,其主要步骤如下。

1.        分配cdev结构:有静态(直接定义)动态(cdev_alloc();)两种方式

2.        初始化cdev结构:使用 cdev_init(struct cdev *cdev, const struct file_operations *fops) 初始化

3.        驱动注册:使用 int cdev_add(struct cdev *p, dev_t dev, unsigned count)//count为该种类型的设备个数注册 

4.        硬件初始化:阅读芯片手册进行硬件设备的初始化

5.        完成操作函数集:实现要用的操作(设备方法)

6.        驱动注销:使用 void cdev_del(struct cdev *p) 注销

5.       字符设备驱动模型及调用关系

下面我通过一张图将字符设备的驱动结构、以及字符设备驱动与用户空间的调用关系进行展示:

6.       遗漏知识

我们内核空间和用户空间的数据交互要用到下面两个函数:

1 copy_from_user();//从用户空间读2 copy_to_user();//写入用户空间 

l  简单字符设备驱动实现

经过上面的分析我们对字符设备有一定了解,下面我们来完成一个最简单的字符设备驱动。我只展示最主要的代码,整个项目工程在https://github.com/wrjvszq/myblongs.git欢迎大家关注。

1.       字符设备驱动编写

因为驱动本身就是一个内核模块,下面的字符设备驱动只实现了部分方法,在后面的博客中我们会基于此驱动慢慢修改,希望大家掌握。

 

 View Code

l  驱动测试

经过上面的代码我们已经实现了一个简单的字符设备驱动,我们下面进行测试。(应用程序在https://github.com/wrjvszq/myblongs.git 上)

1.       加载内核模块

我们使用 insmod memdev.ko 命令加载内核模块

2.       获取设备号

我们的设备号是动态申请到的,所以我们要通过下面的命令查看设备号

 cat /proc/devices 

找到我们的设备memdev的设备号

3.       建立设备文件

使用如下命令建立设备文件

 mknod /dev/文件名 c 主设备号次设备号 

上面命令中文件名为我们在应用程序中打开的文件名

c代表字符设备

主设备号为上一步找到的,我的位249

次设备号非负即可,但不能超过自己所创建的设备数。

比如我的就是 mknod /dev/memdev0 c 249 0 

4.       编译应用程序并测试

使用gcc对应用程序进行编译,然后先使用write对设备进行写入,在使用read对设备读取,完成测试。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩不认真检查作业怎么办 一年级的小孩作业不认真怎么办 一年级学生做题粗心怎么办 一年级的学生做题粗心怎么办 孩子做作业注意力不集中怎么办 小学三年孩子抄答案怎么办 孩子写作业不认真审题怎么办 一年级小孩审题不认真怎么办 孩子审题不认真马虎怎么办 孩子做作业不认真审题怎么办? 考老师考砸了怎么办 重要考试考砸了怎么办 二年级孩子做数学题粗心怎么办 二年级孩子考试粗心怎么办 二年级孩子考试总是粗心怎么办 二年级孩子总是粗心怎么办 小学一年级孩子抄别人作业怎么办 被老师发现抄答案怎么办 考试抄答案被老师发现怎么办 孩子撒谎不写作业怎么办 小学生做题容易马虎出错怎么办 小学生做题老是马虎怎么办 小学生做题马虎不认真怎么办 会做的题总做错怎么办 孩子数学做题粗心怎么办 孩子成绩考差了怎么办 孩子静不下心学习怎么办 孩子考试时总是粗心马虎怎么办 小学二年级学生厌学怎么办 三岁宝宝肚脐痛怎么办 做题速度太慢怎么办 孩子做题不动脑不会转弯怎么办? 孩子做题总是马虎怎么办 孩子做题总是眼高手低怎么办 小孩说幼儿园老师不喜欢他怎么办 初中学生了不喜欢读书怎么办 小孩吐怎么办给揉哪里 8岁了不爱写字怎么办呢 8岁了不会写字怎么办呢 高考做题时犯各种粗心错误怎么办 孩子做题不认真读题怎么办