Linux内核基础设施

1.前言

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

2.链表

1. 链表的基本结构

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

1 struct list_head {
2     struct list_head *next, *prev;
3 };

图 标准双链表

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

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的基本结构

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

注: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则释放该对象

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

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之需

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

3.4 ktype

1 struct kobj_type {
2     void (*release)(struct kobject *kobj);
3     const struct sysfs_ops *sysfs_ops;
4     struct attribute **default_attrs;
5     const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
6     const void *(*namespace)(struct kobject *kobj);
7 };

注: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)

时间: 2024-10-28 00:50:00

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

Linux内核工程导论——基础架构

基础功能元素 workqueue linux下的工作队列时一种将工作推后执行的方式,其可以被睡眠.调度,与内核线程表现基本一致,但又比内核线程使用简单,一般用来处理任务内容比较动态的任务链.workqueue有个特点是自动的根据CPU不同生成不同数目的队列.每个workqueue都可以添加多个work(使用queue_work函数). 模块支持 模块概述 可访问地址空间,可使用资源, 模块参数 用户空间通过"echo-n ${value} > /sys/module/${modulenam

Linux内核工程导论——进程

进程 进程调度 概要 linux是个多进程的环境,不但用户空间可以有多个进程,而且内核内部也可以有内核进程.linux内核中线程与进程没有区别,因此叫线程和进程都是一样的.调度器调度的是CPU资源,按照特定的规则分配给特定的进程.然后占有CPU资源的资源去申请或使用硬件或资源.因此这里面涉及到的几个问题: 对于调度器来说: l  调度程序在运行时,如何确定哪一个程序将被调度来使用CPU资源? n  如何不让任何一个进程饥饿? n  如何更快的定位和响应交互式进程? l  单个CPU只有一个流水线

维护嵌入式 Linux 内核——So Easy

安全漏洞只发生在 Windows 上的好日子正在快速过去.恶意软件黑客和拒绝服务老手们正在越来越多地瞄准过时的嵌入式 Linux 设备,因此在 10 月的欧洲嵌入式 Linux 会议(ELCE)上的几个演讲的主题就与修复 Linux 安全漏洞相关. 最值得去听的讲演之一是 Pengutronix 内核黑客 Jan Lübbe 的<长期维护或管理(或免管理)嵌入式系统 10 年以上>.在总结嵌入式 Linux 中不断增长的安全威胁后,Lübbe 制定了一项计划,以确保长期设备的安全和功能完整.

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

CSDN GitHub Linux内核调试的方式以及工具集锦 LDD-LinuxDeviceDrivers/study/debug 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦 "调试难度本来就是写代码的两倍. 因此, 如果你写代码的时候聪明用尽, 根据定义, 你就没有能耐去调试它了.&qu

一个Linux内核的自旋锁设计-接力嵌套堆栈式自旋锁

锁的开销 锁的开销是巨大的,特别是对于多核多处理来讲.       引入多处理,本身就是为了将并行化处理以提高性能,然而由于存在共享临界区,而这个临界区同时只能有一个线程访问(特别是对于写操作),那么本来并行的执行流在这里被串行化了,形象地看,这里好像是宽阔马路上的一个瓶颈,由于串行化是本质上存在的,因此该瓶颈就是不可消除的.问题是线程执行流如何度过这个瓶颈,很显然,它们谁都绕不开,现在问题是是它们到达这个瓶颈时该怎么办.       很显然,斗殴抢先是一种不合理但实用的简单方案,朴素的自旋锁就

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

简介: 作为一个系统管理程序(hypervisor),Linux® 有几个创新,2.6.32 内核中一个有趣的变化是 KSM(Kernel Samepage Merging)  允许这个系统管理程序通过合并内存页面来增加并发虚拟机的数量.本文探索 KSM 背后的理念(比如存储去耦合).KSM 的实现.以及如何管理 KSM. 服务器虚拟化 虚拟化技术从上世纪 60 年代开始出现,经由 IBM® System/360® 大型机得以流行.50 年过后,虚拟化技术取得了跨越式发展,使得多个操作系统和应用

Linux内核动态跟踪—SYstemTap

导读 :Sloaris中的Dtrace技术曾获<华尔街杂志>2 006技术创新大奖中的金奖.在2005年底,Sun在清华大学举办了Sloaris技术讲座,其中的Dtrace技术,让人耳目一新,它让技术人员摆脱了苦苦阅读静态源代码的日子.那时就期盼,这一技术什么时候出现在Linux内核中. M. Tim Jones又给我们带来了新的文章,他介绍了Linux内核中类似于Dtrace的技术-SystemTap.在对系统性能追逐的当下,了解并掌握此项技术,不论是对于深入Linux内核内部,还是调试内核

Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来.Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大物.撇开营销和模式不谈,Linux 可以说是开源世界中最受欢迎的内核,它在近 30 年的生命时光当中引入了一些真正的规则改变者. Cgroups(2.6.24) 早在 2007 年,Paul Menage 和 Rohit Seth 就在内核中添加了深奥的控制组(cgroups)功能(cgroups 的当前实现是由 T

【华为云技术分享】Linux内核发展史 (1)

openEuler是基于Linux 内核的企业级Linux 服务器操作系统平台的开源社区发行版.openEuler支持鲲鹏架构,可运行在TaiShan服务器上.本技术连载将会从理论基础.源码分析和实操方法三个方面来比较全面地介绍内核编程与应用编程的基础知识,到2020年8月之前主要介绍内核编程部分.通过本连载的介绍,您将对openEuler内核编程和应用编程的理论和实践知识有一个基本的了解.本小节将从Linux内核发展史出发,带您走进openEuler的世界,一起学习操作系统的基础知识和open