mdev是busybox提供的一个工具,用在嵌入式系统中,相当于简化版的udev,作用是在系统启动和热插拔或动态加载驱动程序时, 自动创建设备节点。文件系统中的/dev目录下的设备节点都是由mdev创建的。在加载驱动过程中,根据驱动程序,在/dev下自动创建设备节点。

前面的博客实现了第一个版本,但是需要手工创建字符设备节点,这里使用mdev自动创建。

源代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h> static struct class *first_drv_class;
static struct class_device *first_drv_class_devs;
int auto_major;
static int first_drv_open(struct inode *inode, struct file *file)
{
printk("first_drv_open...\r\n");
return ;
} static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
printk("first_drv_write...\r\n");
return ;
} /* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中指定的对应函数
*/
static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = first_drv_open,
.write = first_drv_write,
};
int fisrt_drv_init(void)
{
auto_major=register_chrdev(, "first_drv", &first_drv_fops); first_drv_class = class_create(THIS_MODULE, "firstdrv");
first_drv_class_devs = class_device_create(first_drv_class, NULL, MKDEV(auto_major, ), NULL, "xyz"); /* /dev/xyz */ return ;
} void fisrt_drv_exit(void)
{
unregister_chrdev(auto_major, "first_drv"); class_device_unregister(first_drv_class_devs);
class_destroy(first_drv_class);
} module_init(fisrt_drv_init);
module_exit(fisrt_drv_exit); MODULE_AUTHOR("http://www.100ask.net");
MODULE_VERSION("0.1.0");
MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver");
MODULE_LICENSE("GPL");

查看现在的字符设备,没有发现有first_drv节点:

加载.ko文件之后出现first_drv设备:

此时查看自动创建的/dev/xyz文件:

然后卸载挂载的驱动first_drv之后,发现/dev/xyz文件自动消失,而且first_drv设备也自动消失了:

这样,就避免了每次都手动创建设备节点了。

Summary:

现在关于内核驱动的函数,我们先学会怎么去使用,跟着韦老师的步伐,之后会有专门的内核源码和驱动的分析,那是入门之后的事情,现在先知道怎么调用API,后面进阶的时候需要阅读源码。毕竟先学会使用,第一可以让自己兴趣更大,一来就阅读源码会很吃力,第二可以快速先入门,第三,可以自己做点小东西。学习是循序渐进的一个过程。

一个字符设备或块设备都有一个主设备号和一个次设备号。主设备号用来标识与设备文件相连的驱动程序,用来反映设备类型。次设备号被驱动程序用来辨别操作的是哪个设备,用来区分同类型的设备。

字符驱动中提及到了次设备号,它可以被用来区分不同的操作:

创建不同的次设备号,我们可以根据次设备号执行不同的操作,比如:

    printf("Usage:\n");
printf("%s <dev> <on|off>\n",file);
printf("eg. \n");
printf("%s /dev/leds on\n", file);
printf("%s /dev/leds off\n", file);
printf("%s /dev/led1 on\n", file);
printf("%s /dev/led1 off\n", file);

./ledtest  /dev/leds on:表示全部led亮

./ledtest  /dev/led1 on:表示第一个led亮

这样的效果可以通过次设备不同来实现。内核中有获取次设备号的函数,在open和write时有不同的操作,还是那句话,具体的内核函数实现,我们之后再说,先在先会使用API就行。

第一个驱动之字符设备驱动(二)mdev的更多相关文章

  1. 【转】深入浅出:Linux设备驱动之字符设备驱动

    深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...

  2. 【Linux驱动】字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...

  3. Linux驱动设计——字符设备驱动(一)

    Linux字符设别驱动结构 cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...

  4. 蜕变成蝶~Linux设备驱动之字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...

  5. 深入浅出:Linux设备驱动之字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...

  6. linux设备驱动之字符设备驱动模型(2)

    在上一篇中我们已经了解了字符设备驱动的原理,也了解了应用层调用内核函数的机制,但是我们每次操作设备,都必须首先通过mknod命令创建一个设备文件名,比如说我们要打开u盘,硬盘等这些设备,难道我们还要自 ...

  7. linux设备驱动之字符设备驱动模型(1)

    一:字符设备驱动 在linux下面,应用层看到的一切皆为文件(名字)所有的设备都是文件,都可以调用open,read,write来操作,而在内核中每个中每个设备有唯一的对应一个设备号: APP   ( ...

  8. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...

  9. [kernel]字符设备驱动、平台设备驱动、设备驱动模型、sysfs几者之间的比较和关联

    转自:http://www.2cto.com/kf/201510/444943.html Linux驱动开发经验总结,绝对干货! 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动 ...

随机推荐

  1. kickstart命令选项

    下面的选项可以放入kickstart文件.如果喜欢使用图形化的界面来创建kickstart文件,可以使用"Kickstart配置"应用程序.(注:如果某选项后面跟随了一个等号(=) ...

  2. List<String> bikeList = Arrays.asList(bikeuuids);

    最近项目中  List<String> bikeList = Arrays.asList(bikeuuids);报错 而且console里面没有特别有用的 bikeList.add(&qu ...

  3. golang项目结构

    一.概述 golang更新了环境变量,导致整个goproject的结构改变: [root@node175 goproject]# tree -L . ├── bin │   └── demo ├── ...

  4. web前端学习笔记-瀑布流的算法分析与代码实现

    瀑布流效果目前应用很广泛,像花瓣,新浪轻博,蘑菇街,美丽说等好多网站都有.也有好多支持该效果的前段框架,今天学习了一下这种效果的实现,不依赖插件,自己动手分析实现过程,为了便于叙述清楚,分析中的一些名 ...

  5. 为什么 c = tf.matmul(a, b) 不立即执行矩阵乘法?

    在 TensorFlow Python API 中,a.b 和 c 是  tf.Tensor  对象.Tensor 对象是指令结果的符号句柄,但它实际上并不存放指令的输出值.相反,TensorFlow ...

  6. Visual C++中的TCHAR

    为了使代码兼容ASCII码和Unicode编码,微软公司还提供了通用字符类型TCHAR. 通用字符类型的含义是,假设在项目属性中选择"Unicode字符集".则TCHAR代表WCH ...

  7. xml中的<![CDATA[]]> 简介

    被<![CDATA[]]>这个标记所包含的内容将表示为纯文本,比如<![CDATA[<]]>表示文本内容“<”.  此标记用于xml文档中,我们先来看看使用转义符的 ...

  8. Android Developers:保存文件

    Android使用一个和其它平台基于硬盘文件系统相似的文件系统.这个课程描述了如何和在Android文件系统使用File APIs读和写文件. 一个File对象适用于读或者写从头到尾没用中断的大型数据 ...

  9. Jmeter录制HTTPS

    Jmeter有录制功能,录制HTTPs需要增加一个证书配置,录制步骤如下: 1.打开jmeter,添加线程组.线程组右键,逻辑控制器>录制控制器 工作台 右键 非测试元件 >HTTP代理服 ...

  10. unity, Gizmos.DrawMesh一个坑

    错误写法(画不出来): void OnDrawGizmos(){ Mesh mesh=new Mesh(); mesh.vertices=... mesh.triangles=... //mesh.R ...