注释仅代表个人理解,仅供参考。

 /*
* class.c - basic device class management
*
* Copyright (c) 2002-3 Patrick Mochel
* Copyright (c) 2002-3 Open Source Development Labs
* Copyright (c) 2003-2004 Greg Kroah-Hartman
* Copyright (c) 2003-2004 IBM Corp.
*
* This file is released under the GPLv2
*
*/ #include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
#include <linux/err.h>
#include <linux/slab.h>
#include "base.h" #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
#define to_class(obj) container_of(obj, struct class, subsys.kobj) static ssize_t
class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
/* [cgw]: 找出包含这个attr的struct class_attribute *指针 */
struct class_attribute * class_attr = to_class_attr(attr);
/* [cgw]: 找出包含这个kobj的struct class *指针,struct class没有直接
* 包含kobj,通过subsys.kobj间接找到struct class *指针
*/
struct class * dc = to_class(kobj);
ssize_t ret = -EIO;
/* [cgw]: class_attr->show指针不为空 */
if (class_attr->show)
/* [cgw]: 调用class_attr->show这个方法 */
ret = class_attr->show(dc, buf);
return ret;
} static ssize_t
class_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count)
{
/* [cgw]: 找出包含这个attr的struct class_attribute *指针 */
struct class_attribute * class_attr = to_class_attr(attr);
/* [cgw]: 找出包含这个kobj的struct class *指针,struct class没有直接
* 包含kobj,通过subsys.kobj间接找到struct class *指针
*/
struct class * dc = to_class(kobj);
ssize_t ret = -EIO; /* [cgw]: class_attr->store指针不为空 */
if (class_attr->store)
/* [cgw]: 调用class_attr->store这个方法 */
ret = class_attr->store(dc, buf, count);
return ret;
} static void class_release(struct kobject * kobj)
{
/* [cgw]: 找出包含这个kobj的struct class *指针,struct class没有直接
* 包含kobj,通过subsys.kobj间接找到struct class *指针
*/
struct class *class = to_class(kobj); pr_debug("class '%s': release.\n", class->name); /* [cgw]: 释放这个类的方法class->class_release指针不为空 */
if (class->class_release)
/* [cgw]: 调用这个方法 */
class->class_release(class);
else
pr_debug("class '%s' does not have a release() function, "
"be careful\n", class->name);
} static struct sysfs_ops class_sysfs_ops = {
.show = class_attr_show,
.store = class_attr_store,
}; static struct kobj_type ktype_class = {
.sysfs_ops = &class_sysfs_ops,
.release = class_release,
}; /* Hotplug events for classes go to the class_obj subsys */
static decl_subsys(class, &ktype_class, NULL); int class_create_file(struct class * cls, const struct class_attribute * attr)
{
int error;
/* [cgw]: cls指针不为空 */
if (cls) {
/* [cgw]: 为cls->subsys.kobj对象创建一个属性文件 */
error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
} else
error = -EINVAL;
return error;
} void class_remove_file(struct class * cls, const struct class_attribute * attr)
{
/* [cgw]: cls指针不为空 */
if (cls)
/* [cgw]: 删除cls->subsys.kobj这个对象的属性文件 */
sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
} static struct class *class_get(struct class *cls)
{
/* [cgw]: cls不为空 */
if (cls)
/* [cgw]: cls->subsys.kobj引用计数+1,并返回cls指针 */
return container_of(subsys_get(&cls->subsys), struct class, subsys);
return NULL;
} static void class_put(struct class * cls)
{
/* [cgw]: cls指针不为空 */
if (cls)
/* [cgw]: 实际上是cls->subsys.kobj引用计数-1 */
subsys_put(&cls->subsys);
} static int add_class_attrs(struct class * cls)
{
int i;
int error = ; /* [cgw]: cls->class_attrs指针不为空 */
if (cls->class_attrs) {
/* [cgw]: cls->class_attrs指向了一个struct class_attribute数组
* 历遍这个数组,并为这个数组里的每一个元素创建一个属性
* 文件
*/
for (i = ; attr_name(cls->class_attrs[i]); i++) {
/* [cgw]: 为cls->subsys.kobj创建一个属性文件 */
error = class_create_file(cls,&cls->class_attrs[i]);
/* [cgw]: 创建失败 */
if (error)
goto Err;
}
}
Done:
return error;
Err:
/* [cgw]: 逐个删除cls->subsys.kobj对应的属性文件列表 */
while (--i >= )
class_remove_file(cls,&cls->class_attrs[i]);
goto Done;
} static void remove_class_attrs(struct class * cls)
{
int i; /* [cgw]: cls->class_attrs指针不为空 */
if (cls->class_attrs) {
/* [cgw]: cls->class_attrs指向了一个struct class_attribute数组
* 历遍这个数组,并删除这个数组里的每一个元素对应的属
* 性文件
*/
for (i = ; attr_name(cls->class_attrs[i]); i++)
/* [cgw]: 删除cls->subsys.kobj对应的一个属性文件 */
class_remove_file(cls,&cls->class_attrs[i]);
}
} int class_register(struct class * cls)
{
int error; pr_debug("device class '%s': registering\n", cls->name); /* [cgw]: 初始化children链表 */
INIT_LIST_HEAD(&cls->children);
/* [cgw]: 初始化devices链表 */
INIT_LIST_HEAD(&cls->devices);
/* [cgw]: 初始化interfaces链表 */
INIT_LIST_HEAD(&cls->interfaces);
/* [cgw]: 初始化kset */
kset_init(&cls->class_dirs);
/* [cgw]: 初始化一个互斥信号量 */
init_MUTEX(&cls->sem);
/* [cgw]: 设置kobj的名字和类的一样 */
error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
/* [cgw]: 设置kobj的名字失败 */
if (error)
return error;
/* [cgw]: cls->subsys.kobj.kset指向class_subsys (kset)
* 实际上是分配了一个kset
*/
subsys_set_kset(cls, class_subsys);
/* [cgw]: 注册子系统,实际上是注册了kset */
error = subsystem_register(&cls->subsys);
/* [cgw]: 注册成功 */
if (!error) {
/* [cgw]: 添加类属性 */
error = add_class_attrs(class_get(cls));
/* [cgw]: cls->subsys.kobj 引用计数-1
* why ????
*/
class_put(cls);
}
return error;
} void class_unregister(struct class * cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
/* [cgw]: 删除这个类的所有属性文件 */
remove_class_attrs(cls);
/* [cgw]: 注销这个子系统,cls->subsys.kobj */
subsystem_unregister(&cls->subsys);
} static void class_create_release(struct class *cls)
{
pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
/* [cgw]: 释放这个已分配的struct class *的内存空间 */
kfree(cls);
} static void class_device_create_release(struct class_device *class_dev)
{
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
/* [cgw]: 释放这个已分配的struct class_device *内存空间 */
kfree(class_dev);
} /* needed to allow these devices to have parent class devices */
static int class_device_create_uevent(struct class_device *class_dev,
char **envp, int num_envp,
char *buffer, int buffer_size)
{
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
return ;
} /**
* class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class
* @name: pointer to a string for the name of this class.
*
* This is used to create a struct class pointer that can then be used
* in calls to class_device_create().
*
* Note, the pointer created here is to be destroyed when finished by
* making a call to class_destroy().
*/
struct class *class_create(struct module *owner, const char *name)
{
struct class *cls;
int retval; /* [cgw]: 分配sizeof(*cls)个字节的内存空间 */
cls = kzalloc(sizeof(*cls), GFP_KERNEL);
/* [cgw]: 分配失败 */
if (!cls) {
retval = -ENOMEM;
goto error;
} /* [cgw]: 给这个类分配一个名字 */
cls->name = name;
/* [cgw]: 这个类属于哪个内核模块 */
cls->owner = owner;
/* [cgw]: 分配用于释放这个struct class类的回调
* 当一个设备从这个类中移除时调用
*/
cls->class_release = class_create_release;
/* [cgw]: 分配用于释放这个struct class_device类的回调
* 当这个类本身被移除时调用
*/
cls->release = class_device_create_release;
/* [cgw]: 注册这个类 */
retval = class_register(cls);
/* [cgw]: 注册失败 */
if (retval)
goto error; return cls; error:
/* [cgw]: 释放这个类 */
kfree(cls);
return ERR_PTR(retval);
} /**
* class_destroy - destroys a struct class structure
* @cls: pointer to the struct class that is to be destroyed
*
* Note, the pointer to be destroyed must have been created with a call
* to class_create().
*/
void class_destroy(struct class *cls)
{
if ((cls == NULL) || (IS_ERR(cls)))
return;
/* [cgw]: 注销这个类cls,这个类必须是由class_create()
* 创建的
*/
class_unregister(cls);
}

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

  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 添加中文注释(3)

    int class_device_register(struct class_device *class_dev) { /* [cgw]: 初始化一个struct class_device */ cl ...

  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. Eclipse与Android源码中ProGuard工具的使用

    由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的 ...

  2. what's this? 浅谈js中this的指向问题

    刚刚学习js的朋友可能和我一样,看到代码中的this总是一脸懵逼,不知道this到底指向谁.经过一段时间的了解,我想跟大家分享下自己的理解. 何时出现this 函数在调用的时候,会自动获得两个特殊变量 ...

  3. Spring整合Ehcache管理缓存

    前言 Ehcache 是一个成熟的缓存框架,你可以直接使用它来管理你的缓存. Spring 提供了对缓存功能的抽象:即允许绑定不同的缓存解决方案(如Ehcache),但本身不直接提供缓存功能的实现.它 ...

  4. Windows Phone 的 TextBox 的实现 PropertyChanged

    比如,View 的文本框 TextBox1 绑定了 ViewModel 的 Msg 属性, 当想把文本框输入的内容输入过程中实时更新到绑定的 Msg ,在Windows Phone 中是无法通过设置  ...

  5. 【Bug】看不见的分隔符: Zero-width space

    今天在调试一段代码的时候,有一个输入不能为空的库函数抛出了异常(为空就会抛出异常,就是这么傲娇).自己暗骂了自己一番,怎么这么大意,于是追溯源头,开始寻找输入控制的地方.但是当我找到时我惊呆了,我明明 ...

  6. 注册表(C#)

    Windowa注册表是包含Windows安装,用户喜好以及以安装软件和设备的所有配置信息的核心储存库.COM组件必须把它的信息出存在注册表中,才能被客户程序使用.注册表也包含了一些系统配置的信息,这些 ...

  7. C# DataGrid根据某列的内容设置行字体加粗 单元格设置对齐方式

    最近做了个功能,DataGrid显示具体内容的时候,根据某列分组. 每个分组具体内容后边,增加一行显示合计信息. 查询数据时,使用了union all将分组数据与明细数据合并起来,使用了排序达到了预期 ...

  8. EF架构~EF异步改造之路~仓储接口的改造~续

    回到目录 返回异步与并行目录 在写完仓储接口的改造改造后,总觉得有个代码的坏味道,这种味道源于它的DRP,即重复的代码太多了,即异步操作和同步操作其实只是在insert,update和delete上有 ...

  9. C++_系列自学课程_第_6_课_bitset集_《C++ Primer 第四版》

    在C语言中要对一个整数的某一个位进行操作需要用到很多的技巧.这种情况在C++里面通过标准库提供的一个抽象数据类型 bitset得到了改善. 一.标准库bitset类型 1.bitset的作用 bits ...

  10. Tomcat下使用c3p0配置jndi数据源

    下载c3p0包: 下载地址:https://sourceforge.net/projects/c3p0/files/?source=navbar 解压后得到包:c3p0-0.9.2.jar,mchan ...