Linux内核之Devices创建过程解 4000 析
2016-11-25 19:55
162 查看
内核版本:2.6.35.7
声明:一部分是我自己整理的,大多数都是参考别人文章整理的。也感谢那些经常发文章教导的大神们。废话不说,进入正题。
参考文章链接
Device的创建是基于kobject和kset。
参考文章链接
1.要明白Device的创建过程,首先要知道它相关的结构体
2.Device的注册
(1)从kset_create_and_add函数入手(Tab键表示函数的层级关系)
kset_create_and_add(“devices”, &device_uevent_ops, NULL);
kset_create(devices, device_uevent_ops, NULL);//创建一个容器
kobject_set_name(&kset->kobj, devices);//设置容器名字
kset_register(kset);//注册要创建的容器
(2)上代码关于kobject_set_name函数和kset_register函数
int kset_register(struct kset *k)
{
int err;
if (!k)
return -EINVAL;
}
kset_init大概就做了一些:初始化devices链表,初始化了链表锁
kobject_add_internal是比较重要的一个函数
(3)至此device目录也就建立起来了,能力有限也只能分析到这。转载一张大神的图片。
![](https://img-blog.csdn.net/20161125201441044)
2.devices_init函数里面的接下来几个函数
跟上面的注册大同小异
声明:一部分是我自己整理的,大多数都是参考别人文章整理的。也感谢那些经常发文章教导的大神们。废话不说,进入正题。
参考文章链接
Device的创建是基于kobject和kset。
参考文章链接
1.要明白Device的创建过程,首先要知道它相关的结构体
struct device { struct device *parent; //指向父节点的指针 struct device_private *p; struct kobject kobj; //把它联系到sysfs中 const char *init_name; //设备的名字 struct device_type *type; struct mutex mutex; struct bus_type *bus; //对设备所在总线的指针 struct device_driver *driver; //对设备所用驱动的指针 void *platform_data; struct dev_pm_info power; u64 *dma_mask; u64 coherent_dma_mask; struct device_dma_parameters *dma_parms; struct list_head dma_pools; struct dma_coherent_mem *dma_mem; struct dev_archdata archdata; dev_t devt; //设备号 spinlock_t devres_lock; struct list_head devres_head; //表示设备的资源 struct klist_node knode_class; //被连入class链表所用的指针 struct class *class; //指向类的指针 const struct attribute_group **groups; //设备属性的集合 void (*release)(struct device *dev); //设备释放所调用的函数 }; struct device_private { struct klist klist_children; //子设备的链表 struct klist_node knode_parent; //连接入父设备链表所用节点 struct klist_node knode_driver; //连接入驱动设备链表所用节点 struct klist_node knode_bus; //连接入总线所用节点 void *driver_data; //存放驱动信息 struct device *device; //指向device_private所属的device };
2.Device的注册
int __init devices_init(void) { devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); if (!devices_kset) return -ENOMEM; dev_kobj = kobject_create_and_add("dev", NULL); if (!dev_kobj) goto dev_kobj_err; sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); if (!sysfs_dev_block_kobj) goto block_kobj_err; sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); if (!sysfs_dev_char_kobj) goto char_kobj_err; return 0; char_kobj_err: kobject_put(sysfs_dev_block_kobj); block_kobj_err: kobject_put(dev_kobj); dev_kobj_err: kset_unregister(devices_kset); return -ENOMEM; }
(1)从kset_create_and_add函数入手(Tab键表示函数的层级关系)
kset_create_and_add(“devices”, &device_uevent_ops, NULL);
kset_create(devices, device_uevent_ops, NULL);//创建一个容器
kobject_set_name(&kset->kobj, devices);//设置容器名字
kset_register(kset);//注册要创建的容器
(2)上代码关于kobject_set_name函数和kset_register函数
static struct kset *kset_create(const char *name, const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) { struct kset *kset; int retval; //为要创建的容器分配内存空间 kset = kzalloc(sizeof(*kset), GFP_KERNEL); if (!kset) return NULL; //设置容器的名字,也就是devices retval = kobject_set_name(&kset->kobj, name); if (retval) { kfree(kset); return NULL; } //绑定uevent_ops,具体我也不知道,毕竟我还是学生,我看了很多文章都没提及 kset->uevent_ops = uevent_ops; //绑定对象的父类,这里是NULL kset->kobj.parent = parent_kobj; //绑定操作这个容器的方法和属性 kset->kobj.ktype = &kset_ktype; kset->kobj.kset = NULL; return kset; }
int kset_register(struct kset *k)
{
int err;
if (!k)
return -EINVAL;
//初始化我们创建好的devices,具体的可以去看我参考的第二篇文章 kset_init(k); err = kobject_add_internal(&k->kobj); if (err) return err; kobject_uevent(&k->kobj, KOBJ_ADD); return 0;
}
kset_init大概就做了一些:初始化devices链表,初始化了链表锁
kobject_add_internal是比较重要的一个函数
static int kobject_add_internal(struct kobject *kobj) { int error = 0; struct kobject *parent; if (!kobj) return -ENOENT; if (!kobj->name || !kobj->name[0]) { WARN(1, "kobject: (%p): attempted to be registered with empty " "name!\n", kobj); return -EINVAL; } parent = kobject_get(kobj->parent); //因为在kset_create中设置了kset->kobj.kset = NULL; //所以下面这个if语句不会进去 if (kobj->kset) { if (!parent) parent = kobject_get(&kobj->kset->kobj); kobj_kset_join(kobj); kobj->parent = parent; } pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n", kobject_name(kobj), kobj, __func__, parent ? kobject_name(parent) : "<NULL>", kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>"); //接下来就创建了目录,具体我也没看懂,因为看函数名字就知道创建了这个device目录,能力有限。请见谅 error = create_dir(kobj); if (error) { kobj_kset_leave(kobj); kobject_put(parent); kobj->parent = NULL; /* be noisy on error issues */ if (error == -EEXIST) printk(KERN_ERR "%s failed for %s with " "-EEXIST, don't try to register things with " "the same name in the same directory.\n", __func__, kobject_name(kobj)); else printk(KERN_ERR "%s failed for %s (%d)\n", __func__, kobject_name(kobj), error); dump_stack(); } else kobj->state_in_sysfs = 1; return error; }
(3)至此device目录也就建立起来了,能力有限也只能分析到这。转载一张大神的图片。
2.devices_init函数里面的接下来几个函数
//创建一个dev的目录 dev_kobj = kobject_create_and_add("dev", NULL); if (!dev_kobj) goto dev_kobj_err; //在dev目录下创建block sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); if (!sysfs_dev_block_kobj) goto block_kobj_err; //在dev目录下创建char sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); if (!sysfs_dev_char_kobj) goto char_kobj_err;
跟上面的注册大同小异
相关文章推荐
- 分析Linux内核创建一个新进程的过程
- Linux内核创建一个新进程的过程
- 分析Linux内核创建一个新进程的过程
- 分析Linux内核创建一个新进程的过程
- 《Linux内核--分析Linux内核创建一个新进程的过程 》 20135311傅冬菁
- 分析Linux内核创建一个新进程的过程
- Linux内核创建socket的过程
- 实验六:分析Linux内核创建一个新进程的过程
- linux内核分析第六周-分析Linux内核创建一个新进程的过程
- 分析Linux内核创建一个新进程的过程
- Linux2.6内核进程创建过程分析
- Linux内核作业--分析Linux内核创建一个新进程的过程
- Linux内核设计第六周学习总结 分析Linux内核创建一个新进程的过程
- Linux内核创建socket的过程(1)
- 分析Linux内核创建一个新进程的过程
- 分析Linux内核创建一个新进程的过程
- [转载] 分析Linux内核创建一个新进程的过程
- 实验六:分析Linux内核创建一个新进程的过程
- 分析Linux内核创建一个新进程的过程
- 20135202闫佳歆--week6 分析Linux内核创建一个新进程的过程——实验及总结