1.前言

本文主要介绍Linux内核实现的基本数据类型,包括链表,内核对象,内核对象引用计数,内核对象集合,

2.链表

1. 链表的基本结构

内核链表可以将任何类型的数据结构连接起来,链表结构如下:

 struct list_head {
struct list_head *next, *prev;
};

图 标准双链表

典型的循环双向链表如上图所示。

2. 链表相关API

LIST_HEAD(list_name) 定义一个list_head结构体,next和pre成员均初始化为当前新创建的list_head

list_add(new,head) 用于head元素之后紧接着插入new元素

list_add_tail(new,head) 在head元素前面插入new元素,由于是循环链表,实际是将new元素插入到末尾

list_del(entry) 从链表中删除一项 

list_empty(head) 检查链表是否为空

list_splice(list, head) 合并两个链表,把list插入到另一个链表head的后面

list_entry(ptr, tpe, member) ptr是某数据结构中指向list_head成员的指针,type是该数据结构的类型,member是该数据结构中list_head成员变量名

list_for_each(pos, head) 用于遍历链表的所有元素。pos表示链表的当前位置,head指定了表头

3. 内核对象

3.1 kobject

1. kobject的基本结构

 struct kobject {
const char *name; /*kobject的名字*/
struct list_head entry;/*用于将kobject放置到一个链表中*/
struct kobject *parent;/*指向当前kobject的父对象,用于建立层次结构*/
struct kset *kset; /*用于将对象与其他对象放到一个集合中*/
struct kobj_type *ktype; /*提供了kobject的更多属性,最重要的是释放该数据结构资源的析构器函数*/
struct kernfs_node *sd; /* sysfs directory entry */
struct kref kref; /*用于简化引用计数*/
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
unsigned int state_initialized:;
unsigned int state_in_sysfs:;
unsigned int state_add_uevent_sent:;
unsigned int state_remove_uevent_sent:;
unsigned int uevent_suppress:;
};

注:kobject不是通过指针与其他数据结构连接,而必须直接嵌入到其他数据结构中,这样通过管理kobject达到了包含kobject对象的管理。由于kobject会嵌入到许多数据结构中,因此要保持kobject结构较小。

2. kobject的API

struct kobject *kobject_get(struct kobject *kobj) 增加kobject的引用计数

void kobject_put(struct kobject *kobj) 减少kobject的引用计数

void kobject_init(struct kobject *kobj, struct kobj_type *ktype) 初始化kobject结构体,即将引用计数设为0,并初始化kobject的链表成员

int kobject_add(struct kobject *kobj, struct kobject *parent, 将kobject加入sysfs中显示
const char *fmt, ...) int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, struct kobject *parent, const char *fmt, ...) kobject_init和kobject_add的合并操作 struct kobject *kobject_create(void) 为一个kobject分配空间,并调用kobject_init初始化 struct kobject *kobject_create_and_add(const char *name, struct kobject *parent) kobject_create和kobject_add的合并操作 static void kobject_cleanup(struct kobject *kobj) 在不需要kobject(以及包含kobject的对象)时释放kobject占用的资源

3.2 kref

1.kref结构体

引用计数用来检测内核中有多少地方使用了某个对象,当内核一个部分包含某个对象的信息时,需要将该对象对应kobject的kref加1,不需要时则减1,如果减为0则释放该对象

 struct kref {
atomic_t refcount; /*原子计数,给出内核中当期使用某个对象的计数,在计数为0时,kobject就可以从内存中删除了*/
};

2.kref的API

static inline void kref_init(struct kref *kref) 初始化kref,即将refcount初始化为1

static inline void kref_get(struct kref *kref)  要使用某个对象必须将对应的kobject的引用计数加1

static inline int kref_sub(struct kref *kref, unsigned int count,
void (*release)(struct kref *kref)) 对象不在使用则将对应的kref减1,如果引用计数为0则调用release释放kobject

3.3 kset

kset是kobject应用的第一个例子,因此它是用kobject 进行管理的,它与kset中包含的各个kobject无关,此处的kobject只是纯粹为了管理kset之需

 struct kset {
struct list_head list; /*用于链接当前kset中所有的kobject的链表*/
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops; /*提供了若干函数指针,用于将kset的相关信息透给应用层*/
};

3.4 ktype

 struct kobj_type {
void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};

注:ktype与kset没有关系,kset已经提供了集合功能,ktype提供了与sysfs文件系统相关的接口。如果多个kobject导出类似的信息,则可以共享一个ktype提供所需要的方法

4.  数据类型

  • 数据类型定义

typedef  为避免依赖体系结构的相关特性,如sector_t, pid_t等

  • 字节序

cpu_to_le64 将64位数据类型转换为小端序格式

le64_to_cpu 将64位小端序格式转换为64位cpu端格式

  • per-cpu变量

可有效避免多处理器并发访问同个变量引发的并发问题

DEFINE_PER_CPU(name, type) name是变量名, type是数据类型

get_cpu(name, cpu) 获取当前cpu上创建的变量实例

smp_processor_id() 返回当前 cpu 的id

  • 访问用户空间

__user 使用此标记来标识指向用户空间的指针

5. 参考文档

[1] 深入Linux内核架构(PLKA)

Linux内核基础设施的更多相关文章

  1. Linux内核的总结认识

    转载博文: http://www.linuxdiyf.com/linux/11234.html 1.内核是怎样实现其管理的职能? 以前在学校时一直不能理解内核是怎么做管理?比如内核如何知道在什么时候对 ...

  2. KSM剖析——Linux 内核中的内存去耦合

    简介: 作为一个系统管理程序(hypervisor),Linux® 有几个创新,2.6.32 内核中一个有趣的变化是 KSM(Kernel Samepage Merging)  允许这个系统管理程序通 ...

  3. 现在的 Linux 内核和 Linux 2.6 的内核有多大区别?

    作者:larmbr宇链接:https://www.zhihu.com/question/35484429/answer/62964898来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  4. 2019-2020-9 20199317 《Linux内核原理与分析》第九周作业

    第8章  进程的切换和系统的一般执行过程 1  进程调度的时机 1.1  硬终端与软中断 进程调度的时机都与中断相关,中断有很多种,都是程序执行过程中的强制性转移,转移到操作系统内核相应的处理程序.中 ...

  5. Linux内核调试的方式以及工具集锦【转】

    转自:https://blog.csdn.net/gatieme/article/details/68948080 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

  6. Linux内核调试的方式以及工具集锦

    原文:https://blog.csdn.net/gatieme/article/details/68948080 CSDN GitHubLinux内核调试的方式以及工具集锦 LDD-LinuxDev ...

  7. 探索Linux内核:Kconfig / kbuild的秘密

    探索Linux内核:Kconfig / kbuild的秘密 文章目录 探索Linux内核:Kconfig / kbuild的秘密 深入了解Linux配置/构建系统的工作原理 Kconfig kbuil ...

  8. Linux内核学习之工作队列

    Author       : Toney Email         : vip_13031075266@163.com Date          : 2020.12.02 Copyright : ...

  9. Linux 内核概述 - Linux Kernel

    Linux 内核学习笔记整理. Unix unix 已有40历史,但计算机科学家仍认为其是现存操作系统中最大和最优秀的系统,它已成为一种传奇的存在,历经时间的考验却依然声名不坠. 1973 年,在用 ...

随机推荐

  1. Java 实现金额转换 代码示例

    金额转换,阿拉伯数字的金额转换成中国传统的形式如: (¥1011)→(壹仟零壹拾壹元整)输出. 分析: 金额转换,在开发财务相关软件时会经常用到,也是软件本地化的一个需要.一般开发公司或者团队都有相应 ...

  2. 洛谷 P3705 [SDOI2017]新生舞会 解题报告

    P3705 [SDOI2017]新生舞会 题目描述 学校组织了一次新生舞会,\(Cathy\)作为经验丰富的老学姐,负责为同学们安排舞伴. 有\(n\)个男生和\(n\)个女生参加舞会买一个男生和一个 ...

  3. python测试webservice接口

    1.下载库:https://pypi.python.org/pypi/suds-jurko 2.解压后,进入到解压目录,安装库:python3 setup.py install 3.测试获取手机归属地 ...

  4. bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)

    直接建图边数太多,用线段树优化一下 然后缩点,记下来每个点里有多少个炸弹 然后按拓扑序反向dp一下就行了 #include<bits/stdc++.h> #define pa pair&l ...

  5. HDU 3338 Kakuro Extension (网络流,最大流)

    HDU 3338 Kakuro Extension (网络流,最大流) Description If you solved problem like this, forget it.Because y ...

  6. P1274 魔术数字游戏 naive搜索+剪枝

    真的naive...... 我把所有能剪的枝都剪了才过的.否则就是TTT 还有个很神奇的事:数组作为参数传进递归函数时会造成上一层函数里的数组的改变.这个我TM调了一天. 下面奉上代码 #includ ...

  7. JAVA8给我带了什么——流的概念和收集器

    到现在为止,笔者不敢给流下定义,从概念来讲他应该也是一种数据元素才是.可是在我们前面的代码例子中我们可以看到他更多的好像在表示他是一组处理数据的行为组合.这让笔者很难去理解他的定义.所以笔者不表态.各 ...

  8. NO.11 复制时勿忘其每个成分

    1.Coping 函数应该确保复制对象内的"每一个成员变量",和调用合适的 "base class"构造函数(base class 某些成员往往是private ...

  9. spring-data-jpa与mybatis的对比

    Spring Data JPA 与 MyBatis对比 Spring Data JPA是Spring Data的子模块.使用Spring Data,使得基于“repositories”概念的JPA实现 ...

  10. Study 2 —— 图片热点区域

    标记<map>和<area><img src="图片" usemap="#名称"><map id="#名称& ...