作者:Younger Liu

本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。

sysfs文件系统下的每个目录对应于一个kobj,kset是kobj的封装,内嵌了一个kobj,其代表kset自身,ktype代表属性操作集,但由于通用性,因此把ktype单独剥离出来,kobj,kset,ktype成为了各个驱动模型最底层的关联元素,并由此形成了sys下的各种拓扑结构。

1         kobject,kset,子系统层次结构

内核通常用kobject
结构将各个对象连接起来组成一个分层的结构体系。

一个 kset是嵌入到相同类型结构的 kobject的集合。

structkobj_type 关注的是对象的类型,而structkset关心的是对象的集合,可认为kset是kobjects的顶层容器类。每个
kset在内部包含自己的 kobject,并可以用多种处理kobject的方法处理kset。
kset总是在 sysfs中出现;一旦设置了 kset并把它添加到系统中,
将在 sysfs
中创建一个目录;kobjects不必在 sysfs中表示,但kset中的每一个
kobject成员都在sysfs中得到表述。

2         如何实现sysfs接口

kobject是在 sysfs虚拟文件系统后的机制。对每个在 sysfs中的目录,在内核中都会有一个
kobject与之对应。每个 kobject都输出一个或多个属性,它在 kobject的
sysfs 目录中以文件的形式出现,其中的内容由内核产生。

当创建kobject
时, 每个 kobject都被给定一系列默认属性。这些属性保存在kobj_type结构中:

struct kobj_type {
void (*release)(struct kobject *);
struct sysfs_ops *sysfs_ops;/*提供实现以下属性的方法*/
struct attribute **default_attrs; /*用于保存类型属性列表(指针的指针) */
}; struct attribute {
char *name;/*属性的名字( 在 kobject 的 sysfs 目录中显示)*/
struct module *owner;/*指向模块的指针(如果有), 此模块负责实现这个属性*/
mode_t mode; /*属性的保护位,modes 的宏定义在 <linux/stat.h>:例如S_IRUGO 为只读属性等等*/
}; /*default_attrs 列表中的最后一个元素必须用 0 填充*/ 

sysfs 读写这些属性是由 kobj_type->sysfs_ops成员中的函数完成的:

struct sysfs_ops { ssize_t (*show)(struct kobject *kobj, struct attribute*attr, char *buffer);

当用户空间读取一个属性时,内核会使用指向 kobject的指针(kobj)和正确的属性结构(*attr)来调用show方法,该方法将给定属性值编码进缓冲(buffer)(注意不要越界(
PAGE_SIZE字节)),并返回实际数据长度。sysfs的约定要求每个属性应当包含一个可读值;若返回大量信息,需将它分为多个属性.

也可对所有 kobject
关联的属性使用同一个 show
方法,用传递到函数的 attr
指针来判断所请求的属性。有的 show方法包含对属性名字的检查。有的show方法会将属性结构嵌入另一个结构,这个结构包含需要返回属性值的信息,这时可用container_of获得上层结构的指针以返回属性值的信息。

store方法将存在缓冲(buffer)的数据( size为数据的长度,不能超过
PAGE_SIZE )解码并保存新值到属性(*attr),返回实际解码的字节数。store方法只在拥有属性的写权限时才能被调用。此时注意:接收来自用户空间的数据一定要验证其合法性。如果到数据不匹配,返回一个负的错误值。

3         案例

/**********************************************
* Author:lewiyon@hotmail.com
* File name:kset_sample.c
* Description: ksetexample
* Date: 2011-12-10
*********************************************/ #include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h> /*
* 将要创建的文件foo对应的kobj.
*/
struct foo_obj {
struct kobject kobj;
int foo;
int baz;
int bar;
};
/* 通过域成员返回结构体的指针 */
#define to_foo_obj(x) container_of(x, struct foo_obj, kobj) /* 属性 */
struct foo_attribute {
struct attributeattr;
ssize_t(*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);
ssize_t(*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf,size_t count);
}; #define to_foo_attr(x) container_of(x, struct foo_attribute,attr) /*
* 属性foo信息显示函数 (涉及文件目录foo/)
*/
static ssize_t foo_attr_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct foo_attribute*attribute;
struct foo_obj *foo; attribute =to_foo_attr(attr);
foo =to_foo_obj(kobj); if(!attribute->show)
return -EIO; returnattribute->show(foo, attribute, buf);
} /*
* 属性foo存储函数(涉及文件目录foo/) (when a value is writtento a file.)
*/
static ssize_t foo_attr_store(struct kobject *kobj,
struct attribute *attr,
const char *buf, size_t len)
{
struct foo_attribute*attribute;
struct foo_obj *foo; attribute =to_foo_attr(attr);
foo =to_foo_obj(kobj); if(!attribute->store)
return -EIO; returnattribute->store(foo, attribute, buf, len);
} /*
* foo的show/store列表
*/
static const struct sysfs_ops foo_sysfs_ops = {
.show =foo_attr_show,
.store =foo_attr_store,
}; /*
* The release functionfor our object. This is REQUIRED by thekernel to
* have. We free the memory held in our object here.
*/
static void foo_release(struct kobject *kobj)
{
struct foo_obj *foo; foo =to_foo_obj(kobj);
kfree(foo);
} /*
* 当需要从foo文件中读取信息时,调用此函数
*/
static ssize_t foo_show(struct foo_obj *foo_obj, structfoo_attribute *attr,
char*buf)
{
return sprintf(buf,"%d\n", foo_obj->foo);
} /*
* 当往foo文件写入信息时,调用此函数
*/
static ssize_t foo_store(struct foo_obj *foo_obj, structfoo_attribute *attr,
const char *buf, size_t count)
{
sscanf(buf,"%du", &foo_obj->foo);
return count;
} static struct foo_attribute foo_attribute =
__ATTR(foo, 0666,foo_show, foo_store); /*
* foo_ktype的属性列表
*/
static struct attribute *foo_default_attrs[] = {
&foo_attribute.attr,
NULL, /* need to NULL terminate the list ofattributes */
}; /*
* 定义kobj_type结构体
* 指定sysfs_ops,release函数, 属性列表foo_default_attrs
*/
static struct kobj_type foo_ktype = {
.sysfs_ops =&foo_sysfs_ops,
.release =foo_release,
.default_attrs =foo_default_attrs,
}; static struct kset *example_kset;
static struct foo_obj *foo_obj; static struct foo_obj *create_foo_obj(const char *name)
{
struct foo_obj *foo;
int retval; /* allocate thememory for the whole object */
foo =kzalloc(sizeof(*foo), GFP_KERNEL);
if (!foo)
return NULL; foo->kobj.kset =example_kset; /*
* 初始化kobject数据结结构foo->lobj,
* 即在foo->kobj的层次组织kset中创建个名为name的文件foo/foo
* 成功返回0
*/
retval =kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s",name);
if (retval) {
/* 减小kobj的引用计数 */
kobject_put(&foo->kobj);
return NULL;
}
/*
* 发送 KOBJ_ADD / KOBJ_REMOVE 等事件
* We are always responsible for sending theuevent that the kobject
* was added to the system.
*/
kobject_uevent(&foo->kobj,KOBJ_ADD); return foo;
} static void destroy_foo_obj(struct foo_obj *foo)
{
/* 减小kobj的引用计数 */
kobject_put(&foo->kobj);
} static int __init example_init(void)
{
/*
* 动态地在kernel_kobj所对应的目录/sys/kernel/下创建一个目录kset_example
* 并返回kset_example对应的kset
*/
example_kset = kset_create_and_add("kset_example",NULL, kernel_kobj);
if (!example_kset)
return-ENOMEM; foo_obj =create_foo_obj("foo");
if (!foo_obj)
gotofoo_error; return 0; foo_error:
return -EINVAL;
} static void __exit example_exit(void)
{
destroy_foo_obj(foo_obj);
kset_unregister(example_kset);
} module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lewiyon <lewiyon@hotmail.com>"); 

4         参考资料:

sysfs文件系统详解:http://blog.chinaunix.net/u1/55599/showart_1089096.html

sysfs.h源码详析:http://blog.chinaunix.net/u1/55599/showart_1091002.html

作者:Younger Liu

本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。



Linux的kobject机制的更多相关文章

  1. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  2. Linux的io机制

    Linux的io机制 Buffered-IO 和Direct-IO Linux磁盘I/O分为Buffered IO和Direct IO,这两者有何区别呢? 对于Buffered IO: 当应用程序尝试 ...

  3. [内核同步]浅析Linux内核同步机制

    转自:http://blog.csdn.net/fzubbsc/article/details/37736683?utm_source=tuicool&utm_medium=referral ...

  4. Linux内核同步机制--转发自蜗窝科技

    Linux内核同步机制之(一):原子操作 http://www.wowotech.net/linux_kenrel/atomic.html 一.源由 我们的程序逻辑经常遇到这样的操作序列: 1.读一个 ...

  5. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

  6. 【Linux下进程机制】从一道面试题谈linux下fork的运行机制

    今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译: #include "stdio.h" #includ ...

  7. Linux内核同步机制

    http://blog.csdn.net/bullbat/article/details/7376424 Linux内核同步控制方法有很多,信号量.锁.原子量.RCU等等,不同的实现方法应用于不同的环 ...

  8. Linux内核OOM机制的详细分析(转)

    Linux 内核 有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了 防止内存耗尽而内核会把该进程杀掉.典 ...

  9. linux内存管理机制

    物理内存和虚拟内存 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念. 物理内存就是系统 ...

随机推荐

  1. PHP服务器脚本 PHP内核探索:新垃圾回收机制说明

    在5.2及更早版本的PHP中,没有专门的垃圾回收器GC(Garbage Collection),引擎在判断一个变量空间是否能够被释放的时候是依据这个变量的zval的refcount的值,如果refco ...

  2. oracle 11g centos6 安装

    选型:32位的内存是个瓶颈,已经是64位的时代了.使用64位的CentOS6 和 64位的Oracle 11g R2在虚拟机器安装,采用hostonly方式设置网络注意:能上网的网卡要设置一下ICS( ...

  3. 深入理解CPU和异构计算芯片GPU/FPGA/ASIC (上篇)

    王玉伟,腾讯TEG架构平台部平台开发中心基础研发组资深工程师,专注于为数据中心提供高效的异构加速云解决方案.目前,FPGA已在腾讯海量图片处理以及检测领域已规模上线. 随着互联网用户的快速增长,数据体 ...

  4. iOS回顾笔记(09) -- Cell的添加、删除、更新、批量操作

    iOS回顾笔记(09) -- Cell的添加.删除.更新.批量操作 项目中经常有对UITableViewCell做各种操作的需求: 添加一个新的cell 删除某行cell 刷新cell上某行数据(如修 ...

  5. 一键部署ETCD集群脚本

    这里使用三个节点,系统版本为CentOS7 # vim deploy-etcd.sh #!/bin/bash set -x set -e #更改这里的IP, 只支持部署3个节点etcd集群 decla ...

  6. 疯狂的 JAVA 后++

    一.x++ 所以执行完x++之后,局部变量区的x值,直接为2: iinc: 指定int型变量增加指定的值,注意是变量,我的解释是iinc直接对局部变量操作,而不是对操作栈进行操作! ★★★★ OUTP ...

  7. 在Selenium Webdriver中使用XPath Contains、Sibling函数定位

    前言 在一般情况下,我们通过简单的xpath即可定位到目标元素,但对于一些既没id又没name,而且其他属性都是动态的情况就很难通过简单的方式进行定位了. 在这种情况下,我们需要使用xpath1.0内 ...

  8. POST与GET

    面试如果被问到这个问题,相信很多人都是会心一笑,答案随口而来: 1.GET在浏览器回退时是无害的,而POST会再次提交请求. 2.GET请求会被浏览器主动cache,而POST不会,除非手动设置. 3 ...

  9. Linux常用命令List

    参考<linux命令行大全> 一.文件命令 cd - 切换为之前目录 wc -l -w file cmd --help apropos keyword apropos cpu > t ...

  10. 和我一步步部署 kubernetes 集群

    和我一步步部署 kubernetes 集群 本系列文档介绍使用二进制部署最新 kubernetes v1.6.1 集群的所有步骤,而不是使用 kubeadm 等自动化方式来部署集群: 在部署的过程中, ...