int class_device_register(struct class_device *class_dev)
{
/* [cgw]: 初始化一个struct class_device */
class_device_initialize(class_dev);
/* [cgw]: 添加一个struct class_device */
return class_device_add(class_dev);
} /**
* class_device_create - creates a class device and registers it with sysfs
* @cls: pointer to the struct class that this device should be registered to.
* @parent: pointer to the parent struct class_device of this new device, if any.
* @devt: the dev_t for the char device to be added.
* @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name
*
* This function can be used by char device classes. A struct
* class_device will be created in sysfs, registered to the specified
* class.
* A "dev" file will be created, showing the dev_t for the device, if
* the dev_t is not 0,0.
* If a pointer to a parent struct class_device is passed in, the newly
* created struct class_device will be a child of that device in sysfs.
* The pointer to the struct class_device will be returned from the
* call. Any further sysfs files that might be required can be created
* using this pointer.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct class_device *class_device_create(struct class *cls,
struct class_device *parent,
dev_t devt,
struct device *device,
const char *fmt, ...)
{
va_list args;
struct class_device *class_dev = NULL;
int retval = -ENODEV; /* [cgw]: cls为空或错误 */
if (cls == NULL || IS_ERR(cls))
goto error; /* [cgw]: 分配sizeof(*class_dev)字节大小的内存空间 */
class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
/* [cgw]: 分配失败 */
if (!class_dev) {
retval = -ENOMEM;
goto error;
} /* [cgw]: 分配设备号 */
class_dev->devt = devt;
/* [cgw]: 分配一个struct device */
class_dev->dev = device;
/* [cgw]: 分配一个struct class */
class_dev->class = cls;
/* [cgw]: 分配一个parent struct class_device */
class_dev->parent = parent;
/* [cgw]: 分配release方法 */
class_dev->release = class_device_create_release;
/* [cgw]: 分配uevent方法 */
class_dev->uevent = class_device_create_uevent; va_start(args, fmt);
/* [cgw]: 把args格式化到字符串fmt中,填装到class_dev->class_id */
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
va_end(args);
/* [cgw]: 注册一个class_dev */
retval = class_device_register(class_dev);
if (retval)
goto error; return class_dev; error:
/* [cgw]: 释放class_dev的内存空间 */
kfree(class_dev);
return ERR_PTR(retval);
} void class_device_del(struct class_device *class_dev)
{
struct class *parent_class = class_dev->class;
struct class_device *parent_device = class_dev->parent;
struct class_interface *class_intf; /* [cgw]: parent_class不为空 */
if (parent_class) {
/* [cgw]: 获取信号量 */
down(&parent_class->sem);
/* [cgw]: 删除class_dev->node节点 */
list_del_init(&class_dev->node);
/* [cgw]: 历遍class_intf->node链表,直到回到parent_class->interfaces节点 */
list_for_each_entry(class_intf, &parent_class->interfaces, node)
/* [cgw]: class_intf->remove指针不为空 */
if (class_intf->remove)
/* [cgw]: 调用remove方法 */
class_intf->remove(class_dev, class_intf);
/* [cgw]: 释放信号量 */
up(&parent_class->sem);
} /* [cgw]: class_dev->dev指针不为空 */
if (class_dev->dev) {
/* [cgw] : 从class_dev->dev->kobj对象目录下删除一个名字为
* class_dev->class->name+class_dev->kobj->k_name的链表
*/
remove_deprecated_class_device_links(class_dev);
/* [cgw]: class_dev->kobj目录下,删除名为device的链表 */
sysfs_remove_link(&class_dev->kobj, "device");
}
/* [cgw]: class_dev->kobj目录下,删除名为subsystem的链表 */
sysfs_remove_link(&class_dev->kobj, "subsystem"); /* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->uevent_attr->attr
* 属性文件
*/
class_device_remove_file(class_dev, &class_dev->uevent_attr);
/* [cgw]: class_dev->devt_attr指针不为空 */
if (class_dev->devt_attr)
/* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->devt_attr->attr
* 属性文件
*/
class_device_remove_file(class_dev, class_dev->devt_attr);
/* [cgw]: 历遍class_dev->class->class_dev_attrs[]数组,如果该属性名字不为空,
* 则对应地删除一个属性文件
*/
class_device_remove_attrs(class_dev);
/* [cgw]: 历遍class_dev->groups[],删除所有属性组 */
class_device_remove_groups(class_dev); /* [cgw]: 通知用户空间,产生一个KOBJ_REMOVE事件 */
kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
/* [cgw]: 删除kobj对象目录,从kset链表中删除class_dev->kobj */
kobject_del(&class_dev->kobj); /* [cgw]: parent_device->kobj引用计数-1 */
class_device_put(parent_device);
/* [cgw]: parent_class->kobj引用计数-1 */
class_put(parent_class);
} void class_device_unregister(struct class_device *class_dev)
{
pr_debug("CLASS: Unregistering class device. ID = '%s'\n",
class_dev->class_id);
/* [cgw]: 删除struct class_device */
class_device_del(class_dev);
/* [cgw]: class_dev->kobj引用计数-1 */
class_device_put(class_dev);
} /**
* class_device_destroy - removes a class device that was created with class_device_create()
* @cls: the pointer to the struct class that this device was registered * with.
* @devt: the dev_t of the device that was previously registered.
*
* This call unregisters and cleans up a class device that was created with a
* call to class_device_create()
*/
void class_device_destroy(struct class *cls, dev_t devt)
{
struct class_device *class_dev = NULL;
struct class_device *class_dev_tmp; /* [cgw]: 获得信号量 */
down(&cls->sem);
/* [cgw]: 返回class_dev_tmp指针,历遍class_dev_tmp链表,
* 查找与cls->children相等的节点class_dev_tmp->node
*/
list_for_each_entry(class_dev_tmp, &cls->children, node) {
/* [cgw]: 找到该节点,设备号为devt */
if (class_dev_tmp->devt == devt) {
/* [cgw]: class_dev指向class_dev_tmp */
class_dev = class_dev_tmp;
break;
}
}
/* [cgw]: 释放信号量 */
up(&cls->sem); /* [cgw]: class_dev指针不为空 */
if (class_dev)
/* [cgw]: 注销这个class_dev */
class_device_unregister(class_dev);
} struct class_device * class_device_get(struct class_device *class_dev)
{
/* [cgw]: class_dev指针不为空 */
if (class_dev)
/* [cgw]: class_dev->kobj引用计数+1
* 并根据kobj找到包含这个kobj的结构体指针
*/
return to_class_dev(kobject_get(&class_dev->kobj));
return NULL;
} void class_device_put(struct class_device *class_dev)
{
/* [cgw]: class_dev指针不为空 */
if (class_dev)
/* [cgw]: class_dev->kobj引用计数-1 */
kobject_put(&class_dev->kobj);
} int class_interface_register(struct class_interface *class_intf)
{
struct class *parent;
struct class_device *class_dev;
struct device *dev; /* [cgw]: class_intf或class_intf->class指针为空 */
if (!class_intf || !class_intf->class)
return -ENODEV; /* [cgw]: class_intf->class->subsys->kset.kobj引用计数+1,
* parent指向class_intf->class
*/
parent = class_get(class_intf->class);
/* [cgw]: parent指针为空 */
if (!parent)
return -EINVAL; /* [cgw]: 获取信号量 */
down(&parent->sem);
/* [cgw]: 添加一个新节点class_intf->node,位于parent->interfaces节点前 */
list_add_tail(&class_intf->node, &parent->interfaces); /* [cgw]: class_intf->add指针不为空 */
if (class_intf->add) {
/* [cgw]: 返回class_dev指针,历遍class_dev链表,
* 调用每个节点node对应的add方法
*/
list_for_each_entry(class_dev, &parent->children, node)
/* [cgw]: 调用与node (class_dev)对应的add方法 */
class_intf->add(class_dev, class_intf);
} /* [cgw]: class_intf->add_dev指针不为空 */
if (class_intf->add_dev) {
/* [cgw]: 返回dev指针,历遍dev链表,
* 调用每个节点node对应的add_dev方法
*/
list_for_each_entry(dev, &parent->devices, node)
/* [cgw]: 调用与node (dev)对应的add_dev方法 */
class_intf->add_dev(dev, class_intf);
}
/* [cgw]: 释放信号量 */
up(&parent->sem); return ;
} void class_interface_unregister(struct class_interface *class_intf)
{
/* [cgw]: parent指针指向class_intf->class */
struct class * parent = class_intf->class;
struct class_device *class_dev;
struct device *dev; /* [cgw]: parent指针为空 */
if (!parent)
return; /* [cgw]: 获取信号量 */
down(&parent->sem);
/* [cgw]: 删除一个节点class_intf->node */
list_del_init(&class_intf->node);
/* [cgw]: class_intf->remove指针不为空 */
if (class_intf->remove) {
/* [cgw]: 返回class_dev指针,历遍class_dev链表,
* 调用每个节点node对应的remove方法
*/
list_for_each_entry(class_dev, &parent->children, node)
/* [cgw]: 调用与node (class_dev)对应的remove方法 */
class_intf->remove(class_dev, class_intf);
} /* [cgw]: class_intf->remove_dev指针不为空 */
if (class_intf->remove_dev) {
/* [cgw]: 返回dev指针,历遍dev链表,
* 调用每个节点node对应的remove_dev方法
*/
list_for_each_entry(dev, &parent->devices, node)
/* [cgw]: 调用与node (class_dev)对应的remove_dev方法 */
class_intf->remove_dev(dev, class_intf);
}
/* [cgw]: 释放信号量 */
up(&parent->sem); /* [cgw]: parent->subsys->kobj引用计数-1 */
class_put(parent);
} int __init classes_init(void)
{
int retval; retval = subsystem_register(&class_subsys);
if (retval)
return retval; /* ick, this is ugly, the things we go through to keep from showing up
* in sysfs... */
subsystem_init(&class_obj_subsys);
if (!class_obj_subsys.kobj.parent)
class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
return ;
} EXPORT_SYMBOL_GPL(class_create_file);
EXPORT_SYMBOL_GPL(class_remove_file);
EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
EXPORT_SYMBOL_GPL(class_create);
EXPORT_SYMBOL_GPL(class_destroy); EXPORT_SYMBOL_GPL(class_device_register);
EXPORT_SYMBOL_GPL(class_device_unregister);
EXPORT_SYMBOL_GPL(class_device_initialize);
EXPORT_SYMBOL_GPL(class_device_add);
EXPORT_SYMBOL_GPL(class_device_del);
EXPORT_SYMBOL_GPL(class_device_get);
EXPORT_SYMBOL_GPL(class_device_put);
EXPORT_SYMBOL_GPL(class_device_create);
EXPORT_SYMBOL_GPL(class_device_destroy);
EXPORT_SYMBOL_GPL(class_device_create_file);
EXPORT_SYMBOL_GPL(class_device_remove_file);
EXPORT_SYMBOL_GPL(class_device_create_bin_file);
EXPORT_SYMBOL_GPL(class_device_remove_bin_file); EXPORT_SYMBOL_GPL(class_interface_register);
EXPORT_SYMBOL_GPL(class_interface_unregister);

class.c 添加中文注释(3)的更多相关文章

  1. Python中添加中文注释报错SyntaxError: Non-UTF-8 code starting with '\xc1'

    问题:在文本编辑器中编辑Python文件时添加中文注释,运行python文件时报错.SyntaxError: Non-UTF-8 code starting with '\xc1' 解决方法:在文本开 ...

  2. char_dev.c 添加中文注释

    char_dev.c里的中文注释,仅代表个人理解,仅供参考.如有错误之处,请指出,谢谢! /* * linux/fs/char_dev.c * * Copyright (C) 1991, 1992 L ...

  3. 在mapper.xml映射文件中添加中文注释报错

    问题描述: 在写mapper.xml文件时,想给操作数据库语句添加一些中文注释,添加后运行报如下错误: 思考 可能是写了中文注释,编译器在解析xml文件时,未能成功转码,从而导致乱码.但是文件开头也采 ...

  4. class.c 添加中文注释(1)

    注释仅代表个人理解,仅供参考. /* * class.c - basic device class management * * Copyright (c) 2002-3 Patrick Mochel ...

  5. class.c 添加中文注释(2)

    /* Class Device Stuff */ int class_device_create_file(struct class_device * class_dev, const struct ...

  6. sass中文注释的解决方法和一些简单用法

    最近用sass来编写项目中的css,发现不能添加中文注释,报错如下 于是查阅了一下发现需要在scss文件顶部加上@charset "utf-8"即可解决. 在此顺便记录一些sass ...

  7. 关于 Keil uVision2 中文注释会显示不完整,字体不正常的问题

    在Keil中添加中文注释经常出现这样情况: ,注释文字不正常! 解决方案:Edit---->Option----->选择color&fonts选项卡中的Editor c Files ...

  8. Eclipse MyBatis generator 1.3.7插件的核心包(中文注释)

    一.最近刚搭建一个项目框架,使用springboot + mybatis,但是在使用Eclipse开发时发现开发mybatis的Dao.mapper.xml和entity时特别不方便,手工去写肯定是不 ...

  9. mysql数据库导出模型到powerdesigner,PDM图形窗口中显示数据列的中文注释

    1,mysql数据库导出模型到powerdesigner 2,CRL+Shift+X 3,复制以下内容,执行 '******************************************** ...

随机推荐

  1. JS原生第三篇 (帅哥)

    1.1 数 组 1. 数组           看电影    电影院  座位 大的变量     里面可以放很多的值 var  arr = [1,3,57]; var ar = new Array(); ...

  2. 特殊的数据类型: bit、sql_variant、sysname

    在SQL Server中,特殊的数据类型主要有三个,分别是:bit.sql_variant 和 sysname 一,bit bit类型,只有三个有效值:0,1 和 null,字符串true或false ...

  3. MongoDB安装与故障

    下载完毕后   bin为官方代码   data为自行创建的文件夹 db存在数据 log存在日志   启动MongoDB 通过cmd到db的文件目录 通过mongod.exe代码执行data下的log文 ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(49)-工作流设计-我的申请

    系列目录 提交一个表单后 我们需要一个管理的列表.我的申请,我的申请包含了提交内容的列表状态 状态分:过期,未审核,审核通过,驳回,废弃 列表对应代码 @using App.Admin; @using ...

  5. Android数据存储之SQLCipher数据库加密

    前言: 最近研究了Android Sqlite数据库(文章地址:Android数据存储之Sqlite的介绍及使用)以及ContentProvider程序间数据共享(Android探索之ContentP ...

  6. 你真的会玩SQL吗?和平大使 内连接、外连接

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  7. Zip 压缩和解压技术在 HTML5 中的应用

    JSZip 是一款可以创建.读取.修改 .zip 文件的 javaScript 工具.在 web 应用中,免不了需要从 web 服务器中获取资源,如果可以将所有的资源都合并到一个 .zip 文件中,这 ...

  8. CSS常见居中讨论

    先来一个常见的案例,把一张图片和下方文字进行居中: 首先处理左右居中,考虑到img是一个行内元素,下方的文字内容也是行内元素,因此直接用text-align即可: <style> .con ...

  9. spring框架之javaconfig

    简介:随着java5的推出,加上当年基于纯java annotation的依赖注入框架Guice的出现,spring推出并持续完善了基于java代码和annotation元信息的依赖关系绑定描述方法, ...

  10. spider 配置文件参考

    spider有一个配置文件spider.xml,为xml格式,spider.xml采用DTD进行管理,用于管理spider的所有特性.路由.高可用等. 配置文件支持三种不同的方式进行指定: 1. 通过 ...