设备模型6之热插拔(实例,同时分析了usb的热插拔)

本文探讨了Linux内核中的热插拔机制,通过一个USB设备的实例来说明。介绍了设备驱动如何处理热插拔事件,包括kobject结构、uevent辅助工具、mdev和udev的使用。分析了热插拔过程中涉及的内核函数和用户空间交互,并展示了如何在mdev.conf中配置规则以响应设备变化。

了解一下热插拔

 

Ldd3的话:

现在, 随着 USB的出现, CardBus, PCMCIA,IEEE1394, PCI 热插拔控制器, Linux内核需要能够可靠地运行不管什么硬件从系统中增加或去除.这产生了一个额外的负担给设备驱动作者,因为现在他们必须一直处理一个没有任何通知而突然从地下冒出来的设备.

 

从这句话我们可以看出,热插拔有两个层次,一个是内核设备模型中提供的机制,一个是硬件提供的功能。

我们的实例主要是设备模型中提供的机制。硬件方面有时间的话我举个例子。

 

一些基础知识如udevmdev我就不说了,论坛有。

 

还是linux-3.2.36

kobject中有个结构struct kset_uevent_ops,我没有列出,因为总线已有这个结构,我们是在总线层所以不要去管理这个结构。

简单说一下热插拔过程(论坛也有这些分析)。

./drivers/base/core.c

device_register()->device_add()->kobject_uevent()->

./lib/ kobject_uevent.c

kobject_uevent_env()->call_usermodehelper()netlink_broadcast_filtered()

一个是uevent_helper调用一个是netlink调用,这两个东西又够我写几遍文章了,等有时间我再写吧。现在简单了解。

netlink是为udev实现机制用的

uevent_helper是为mdev实现机制用的

我的arm平台用的是mdev

call_usermodehelper()第一个参数叫path

path --- 用户空间所要启用的应用程序路径

 

mdev时,echo “/sbin/mdev”> /proc/sys/kernel/hotplug把uevent_helper改为“/sbin/mdev”,再把uevent_helper赋给call_usermodehelper(),最终调用mdev。

说实例之前,先说一下mdev配置。//udev的同学自己搞定,我就不说了

# vi /etc/mdev.conf

$MODALIAS=.* root:root777 @modprobe "$MODALIAS"

保存

MODALIAS要和驱动中一致,马上能看到。

这条规则指的是:当收到的环境变量中含有MODALIAS,那么加载MODALIAS代表的模块。

 

实例:

这个是在上一文章的实例基础上做的,如果要了解,你还要先简单了解一下上一实例(设备模型5)。

my_dev.c中修改,我们要答到的目的是加载my_dvc.ko时自动加载my_dvr.ko

修改,红色为增加

 

MODULE_DEVICE_TABLE(my_dvc, my_dvc_table);

 

static ssize_t show_name(struct device *dev, structdevice_attribute *attr, char *buf)

{

    struct my_device*mydev = (struct my_device*)dev->platform_data;

 

    return sprintf(buf,"%s\n", mydev->name);

}

 

static ssize_t show_modalias(struct device *dev, structdevice_attribute *attr, char *buf)

{

    return sprintf(buf,"%s\n", "my_dvr");

}

 

 

static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);

static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);

//这两个文件只是为了输出一些信息,可以不管

static struct attribute *my_dvc_attrs[] = {

    &dev_attr_name.attr,

   &dev_attr_modalias.attr,

    NULL

};

 

static struct attribute_group my_dvc_attr_group =

{

    .attrs          = my_dvc_attrs,

};

 

static const struct attribute_group *my_dvc_attr_groups[] =

{

   &my_dvc_attr_group,

    NULL

};

 

static int my_dvc_uevent(struct device *dev, structkobj_uevent_env *env)

{

    struct my_device*mydev = (struct my_device*)dev->platform_data;

     int i = 0;

    MY_DEBUG("%s_uevent\n",mydev->name);

 

     //实际一般用一些方法获得driver的name,这里就直接写了

    if(add_uevent_var(env, "MODALIAS=%s", "my_dvr"))// MODALIAS和mdev.conf一致

        return -ENOMEM;

 

    while(env->envp[i]!= NULL)//我们做一个调试信息

     {

         MY_DEBUG("%s\n",env->envp[i]);//打印环境变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值