Linux 内核子系统之内存与进程管理子系统

本文详细介绍了Linux内核中的两个关键子系统:内存管理和进程管理。内容包括虚拟地址空间分布、物理地址映射机制、内存分配过程以及进程的状态、描述和调度策略等方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux 内核子系统的组成

 

由以上7个子系统组成。

一、内存管理子系统

职能:

1、从虚拟地址到物理地址映射的管理。

2、物理内存分配的管理。

地址映射管理

 

2.1虚拟地址空间分布

Linux中使用的是虚拟地址,但是在访问硬件的时候使用的是物理地址。比如程序中用malloc函数分配的都是虚拟地址,但是硬件在使用时用的是物理地址,这其中就有一个转化关系。

它所支持的虚拟地址空间是由硬件地址总线宽度决定的,比如32位地址总线支持4GB虚拟内存。

用户空间(0-3G):用户程序。

内核空间(3-4G):直接映射区3G-3G+896MB.

Vmalloc区,

永久内核映射,

固定映射的线性地址。

2.2虚拟地址转化为物理地址

CR3存放了页目录的基地址。

10位和CR3寄存器相加,就可以找到页目录里的页目录项。

页目录项里存放的是页表的基地址。

页表的基地址再加上中间10位的值就可以找到物理页。

物理页再加上最后12位的偏移就可以找到物理页(通常4k)的存储单元了。

 

直接映射区里:虚拟地址=3G+物理地址

Vmalloc区:可以映射到高端和低端内存

永久映射区:高端内存

固定映射的线性地址:固定访问一些寄存器

 

物理内存的分配

 

程序通过malloc等函数先申请到虚拟地址,当需要用到物理地址时通过请页异常获得物理地址。通过Kmalloc得到的虚拟地址时,虚拟地址和物理地址已经绑定了。

 

二、进程管理子系统

程序:存放在磁盘上的一系列代码和数据的可执行映像,是一个静止的实体

进程:是一个执行中的程序,他是动态的实体。

 

进程四要素

1.有一段程序供其执行。这段程序不一定是某个进程所专有,可以与其他进程共用。

2.有进程专用的内核空间堆栈。

3.在内核中有一个task_struct数据结构,即通常所说的“进程控制块”。有了这个数据结构,进程才能成为内核调度的一个基本单位接受内核的调度。

4.有独立的用户空间

 

Linux进程状态

 

1.TASK_RUNNING

进程正在被CPU执行,或者已经准备就绪,随时可以执行。当一个进程刚被创建时,就处于TASK_RUNNING状态。

2.TASK_INTERRUPTINLE

处于等待中的进程,等待条件为真时被唤醒,也可以被信号或者中断唤醒。

3.TASK_UNINTERRUPTINLE

处于等待中的进程,待资源有效时唤醒,但不可以由其它进程通过(signal)或中断唤醒。

4.TASK_KILLABLE

Linux2.6.25新引入的进程睡眠状态,原理类似于TASK_UNINTERRUPTIBLE,但是可以被致命信号(SIGKILL)唤醒。

5.TASK_TRACED

正处于被调试状态的进程

6.TASK_DEAD

进程退出时(调用do_exit),所处的状态。

 

Linux进程的描述

linux内核代码中,线程、进程都使用结构task_struct(sched.h)来表示,它包含了大量描述进程/线程的信息,其中比较重要的有:

Pid_t pid; //进程号

Long state;//进程状态

Int prio;//进程优先级

 

Linux进程调度

学习调度需要掌握哪些知识点

1、调度策略

实时进程的优先级比普通进程高。

SCHED_NORMAL(SCHED_OTHER):普通的分时进程

SCHED_FIFO:先入先出的实时进程

SCHED_RR:时间轮转的实时进程

SCHED_BATCH:批处理进程

SCHED_IDLE:只在系统空闲时才能被调度执行的进程

2、调度时机

 即schedule()函数什么时候被调用?

主动式:

在内核中直接调用schedule()。当进程需要等待资源等而暂时停止运行时,会把自己的状态置于挂起(睡眠),并主动请求调度,让出CPU

范例:

1、current->state = TASK_INTERRUPTIBLE;

2、Schedule();

Current是一个指针,指向当前正在运行的进程的task_struct

被动式:抢占式

分为:用户态抢占(linux2.4linux2.6)和内核态抢占(linux2.6)

用户抢占发生在:

从系统调用返回用户空间。

从中断处理程序返回用户空间。

内核即将返回用户空间的时候,如果need_resched标志被设置,会导致schedule()被调用,即发生用户抢占。

当某个进程耗尽他的时间片时,会设置need_resched标志

当一个优先级更高的进程进入可执行状态的时候,也会设置need_resched标志。

用户态抢占缺陷

进程/线程一旦运行到内核态,就可以一直执行,直到它主动放弃或时间片耗尽为止。这样会导致一些非常紧急的进程或线程将长时间得不到运行,降低整个系统的实时性。

改进方式

允许系统在内核态也支持抢占,更高优先级的进程/线程可以抢占正在内核态运行的低优先级进程/线程。

内核抢占可能发生在:

中断处理程序完成,返回内核空间之前。

当内核代码再一次具有可抢占性的时候,如解锁使能软中断等。

在支持内核抢占的系统中,某些特例下是不允许抢占的;

1内核正在运行中断处理

2内核正在进行中断上下文的Bottom Half (中断的底半部)处理。

硬件中断返回前会执行软中断,此时仍然处于中断上下文中

3进程正持有spinlock自旋锁、writelock/readlock读写锁等

当持有这些锁时,不应该被抢占,否则由于抢占将可能导致其他进程长期得不到锁,而让系统处于死锁状态。

4内核正在执行调度程序scheduler。抢占的原因就是为了进行新的调度,没有理由将调度程序抢占掉再运行调度程序。

为保证linux内核在以上情况下不会被抢占,抢占式内核使用了一个变量preempt_count,称为内核抢占计数。这一变量被设置在进程的thread_info结构中。每当内核要进入以上几种状态时,变量preempt_count就加1,指示内核不允许抢占。每当内核从以上几种状态退出时,变量preempt_count就减1,同时进行可抢占的判断与调度。

3、调度步骤

Schedule函数工作流程如下

1)清理当前运行中的进程;

2)选择下一个要运行的进程;

3)设置新进程的运行环境。

4)进程上下文切换。

目录 1 进程的组织 5 1.1 进程相关数据结构 5 1.1.1 进程的基本信息 6 1.1.2 进程状态 10 1.1.3 TASK_RUNNING状态的进程链表 11 1.1.4 进程间关系 12 1.2 Linux的线程——轻量级进程 15 1.3 进程的创建——do_fork()函数详解 19 1.4 执行进程间切换 33 1.4.1 进程切换之前的工作 33 1.4.2 进程切换实务 —— switch_to宏 37 1.4.3 __switch_to函数 39 1.5 forkvfock系统调用的区别 42 1.6 内核线程 46 1.7 挂起状态进程的组织 49 1.7.1 等待队列头 49 1.7.2 等待队列的操作 50 1.7.3 进程资源限制 55 1.8 系统调用execve() 56 1.8.1 拷贝用户态参数 57 1.8.2 重要的数据结构 61 1.8.3 search_binary_handler函数 66 1.8.4 目标文件的装载和投入运行 69 1.8.5 库函数 92 2 中断控制 94 2.1 中断的分类 94 2.2 中断的硬件环境 95 2.2.1 外部中断请求IRQ 95 2.2.2 中断描述符表 96 2.2.3 中断和异常的硬件处理 97 2.3 中断描述符表 99 2.3.1 中断门、陷阱门及系统门 99 2.3.2 IDT的初步初始化 100 2.4 异常处理 101 2.5 中断处理 106 2.5.1 中断向量 107 2.5.2 IRQ数据结构 108 2.5.3 do_IRQ()函数 113 2.5.4 中断服务例程 115 2.5.5 IRQ线的动态分配 116 2.6 下半部分 117 2.6.1 软中断 118 2.6.2 tasklet 121 2.6.3 工作队列 122 2.7定时器中断 124 2.7.1 时钟定时器 124 2.7.2 定时器中断相关的数据结构 127 2.7.3 定时器中断的上半部分 129 3 进程调度 138 3.1 进程调度的概念 138 3.2 进程调度的数据结构和优先级 141 3.2.1 进程的优先级 141 3.2.2 数据结构 145 3.3 调度程序所使用的函数 151 3.3.1 scheduler_tick函数 151 3.3.2 try_to_wake_up函数 156 3.3.3 recalc_task_prio函数 160 3.4 schedule()函数 163 3.4.1 直接调用 163 3.4.2 延迟调用 164 3.4.3 进程切换之前所做的工作 168 3.4.4 完成进程切换时所执行的操作 171 3.4.5 进程切换后所执行的操作 173 3.5 多处理器运行队列的平衡 175 3.5.1 调度域 176 3.5.2 rebalance_tick()函数 178 3.5.3 load_balance()函数 180 3.5.4 move_tasks()函数 183 3.6 进程退出 187 3.6.1 进程终止 187 3.6.2 进程删除 189 4 进程的并发性体现 191 4.1 内核抢占 193 4.1.1 内核抢占概念 193 4.1.2 同步技术总揽 196 4.2 每CPU变量 197 4.3 原子操作 199 4.4 优化屏障和内存壁垒 203 4.4.1 优化屏障 204 4.4.2 内存壁垒 204 4.5 自旋锁 206 4.6 读写自旋锁 211 4.6.1 为读获取和释放一个锁 213 4.6.2 为写获取或释放一个锁 214 4.7 顺序锁 215 4.8 RCU机制 217 4.9 信号量 219 4.9.1 获取和释放信号量 221 4.9.2 读/写信号量 224 4.9.3 补充信号量 225 4.10 禁止本地中断 226 4.10.1 禁止本地中断 227 4.10.2 禁止下半部(可延迟函数) 229 4.11 一些避免竞争条件的实例 231 4.11.1 引用计数器 231 4.11.2 大内核锁 231 4.11.3 内存描述符读/写信号量 232 4.11.4 slab高速缓存链表的信号量 233 4.11.5 索引节点的信号量 233 4.12 内核同步互斥的总结 233
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值