嵌入式学习-驱动开发前奏-lesson2-内存管理与进程管理子系统

本文主要是介绍嵌入式学习-驱动开发前奏-lesson2-内存管理与进程管理子系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

内存管理子系统

在内核相关一课中,已经介绍过,linux内核一共有7个子系统:
1.SCI
2.Pm
3.MM
4.Arch
5.Vfs
6.Network stack
7.DD

在以后的驱动学习章节中,主要是与 MM PM VFS 这三个相关。
在本章节中则主要讲解MM(内存管理子系统)

1)内存管理模型

这里写图片描述
根据上面的图,可以得知,内存的管理主要是做两个方面的工作:
1:物理内存分配
2:虚拟地址与物理地址的映射

2)地址的映射

这里写图片描述
上面这幅图是地址空间映射图,将其分为三个部分:
1:虚拟地址空间分布
2:虚拟地址转化为物理地址
3:物理内存分配

1.虚拟地址空间分布

根据上图可知,4G的虚拟地址空间又可分为3G的用户空间和1G的内核空间。

1G的内核空间又可分为4部分:
①、直接映射区,最大空间为896MB (896MB以下的内存称之为低端内存,以上则称之为高端内存) 然后减去3G 就可以直接得到物理地址
②、vmalloc区(既可以访问低端区域,也可以访问高端区域)
③、永久内核映射(固定访问高端内存)
④、固定映射的线性地址(和一些特殊的寄存器有关)

2.虚拟地址向物理地址转化

主要是上图第二部分完成的,将其简化为下图
这里写图片描述

具体过程:
1.cr3基地址加上虚拟地址的22–32位指向页目录的某一个地址(cr3指向页目录的基地址)
2.指向页目录的那个地址又指向页表的基地址,然后该地址加上虚拟地址的12–21位指向页表的某一个地址,也就是物理页的基地址
3.物理页的基地址加上虚拟地址的0–11,就得到物理存储单元的地址

3.物理内存的分配

这里写图片描述
linux使用虚拟地址管理方式,只有真正访问物理地址,才分配物理内存

上图,当使用malloc或者vmalloc时,会分配一个虚拟地址,并没有真正访问到物理内存,当需要使用物理内存的时候,会产生一个 请页异常 然后从 空闲页框 中 ,查看是否有空闲的物理内存,当有空闲的时候,机会分配一个物理内存,从而建立起访问关系。
但是当使用kmalloc的时候,slab管理器会直接将虚拟地址和物理地址建立关系。

进程管理子系统

一、进程相关概念

1)进程与程序

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

2)进程四要素

  1. 有一段程序供其执行。这段程序不一定是某个进程所专有,可以与其他进程共用。
  2. 有进程专用的内核空间堆栈。
  3. 在内核中有一个task_struct数据结构,即通常所说的“进程控制块(pcb)”。有了这个数据结构,进程才能成为内核调度的一个基本单位接受内核的调度。
  4. 有独立的用户空间。
    这里写图片描述

3) Linux进程状态

这里写图片描述

linux进程的状态可以将其范围上面三个部分,就绪、执行、阻塞。这是一种典型的三态图,将其进一步细分,
这里写图片描述

1.TASK_RUNNING(就绪、执行)
进程正在被CPU执行,或者已经准备就绪,随时可以执行。当一个进程刚被创建时,就处于TASK_RUNNING状态。
2.TASK_INTERRUPTIBLE(属于三态中的阻塞态)
处于等待中的进程,待等待条件为真时被唤醒,也可以被信号或者中断唤醒。
3. TASK_UNINTERRUPTIBLE
处于等待中的进程,待资源有效时唤醒,但不可以由其它进程通过信号(signal)或中断唤醒。
4. TASK_KILLABLE
Linux2.6.25新引入的进程睡眠状态,原理类似于TASK_UNINTERRUPTIBLE,但是可以被致命信号(SIGKILL)唤醒。
5. TASK_TRACED
正处于被调试状态的进程。
6. TASK_DEAD
进程退出时(调用do_exit),所处的状态。

4) Linux进程描述

在Linux内核代码中,线程、进程都使用结构task_struct(sched.h)来表示,它包含了大量描述进程/线程的信息,其中比较重要的有:
pid_t pid; //进程号
long state; //进程状态
int prio; //进程优先级

在内核源代码sched.h中有关于此结构体的详细描述

二、进程调度

所谓的进程调度就是从就绪的进程中选出最适合的一个来执行。
主要分为:
1、调度策略
2、调度时机
3、调度步骤

1) 调度策略

SCHED_NORMAL(SCHED_OTHER):普通的分时进程
SCHED_FIFO :先入先出的实时进程
SCHED_RR:时间片轮转的实时进程(间隔一定时间,不管是否执行完,换下一个进程运行同样的时间)
SCHED_BATCH:批处理进程
SCHED_IDLE: 只在系统空闲时才能够被调度执行的进程

2 )调度时机

什么时候发生调度?
即schedule()函数什么时候被调用?
schedule()函数在linux内核中完成调度过程

1主动式调度

在内核中直接调用schedule()。当进程需要等待资源等而暂时停止运行时,会把自己的状态置于挂起(睡眠),并主动请求调度,让出CPU。
范例:
1. current->state = TASK_INTERRUPTIBLE; (处于阻塞态)
2. schedule();

2被动式调度

被动式调度又名:抢占式调度。分为:用户态抢占(Linux2.4、Linux2.6)和内核态抢占(Linux2.6)。

2.1用户态抢占
用户抢占发生在:
从系统调用返回用户空间。
从中断处理程序返回用户空间。
内核即将返回用户空间的时候,如果need_resched标志被设置,会导致schedule()被调用,即发生用户抢占。
**当某个进程耗尽它的时间片时,会设置need_resched标志
**当一个优先级更高的进程进入可执行状态的时候,也会设置need_resched标志。

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

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

内核抢占可能发生在:
**中断处理程序完成,返回内核空间之前。
**当内核代码再一次具有可抢占性的时候,如解锁及使能软中断等。

在支持内核抢占的系统中,某些特例下是不允许抢占的:
** 内核正在运行中断处理。
** 内核正在进行中断上下文的Bottom Half(中断的底半部)处理。硬件中断返回前会执行软中断,此时仍然处于中断上下文中。
** 进程正持有spinlock自旋锁、writelock/readlock读写锁等,当持有这些锁时,不应该被抢占,否则由于抢占将可能导致其他进程长期得不到锁,而让系统处于死锁状态。
** 内核正在执行调度程序Scheduler。抢占的原因就是为了进行新的调度,没有理由将调度程序抢占掉再运行调度程序。

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

3) 调度步骤

Schedule函数工作流程如下:
1. 清理当前运行中的进程;
2. 选择下一个要运行的进程;
3. 设置新进程的运行环境;
4. 进程上下文切换 。

菜鸟一枚,如有错误,多多指教。。。

这篇关于嵌入式学习-驱动开发前奏-lesson2-内存管理与进程管理子系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1007134

相关文章

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

Python内存管理机制之垃圾回收与引用计数操作全过程

《Python内存管理机制之垃圾回收与引用计数操作全过程》SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式,本文将介绍如何使用SQLAlc... 目录安装核心概念连接数据库定义数据模型创建数据库表基本CRUD操作创建数据读取数据更新数据删除数据查

在Node.js中使用.env文件管理环境变量的全过程

《在Node.js中使用.env文件管理环境变量的全过程》Node.js应用程序通常依赖于环境变量来管理敏感信息或配置设置,.env文件已经成为一种流行的本地管理这些变量的方法,本文将探讨.env文件... 目录引言为什么使php用 .env 文件 ?如何在 Node.js 中使用 .env 文件最佳实践引

Java中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例解析

《Java中的分布式系统开发基于Zookeeper与Dubbo的应用案例解析》本文将通过实际案例,带你走进基于Zookeeper与Dubbo的分布式系统开发,本文通过实例代码给大家介绍的非常详... 目录Java 中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例一、分布式系统中的挑战二

python库pydantic数据验证和设置管理库的用途

《python库pydantic数据验证和设置管理库的用途》pydantic是一个用于数据验证和设置管理的Python库,它主要利用Python类型注解来定义数据模型的结构和验证规则,本文给大家介绍p... 目录主要特点和用途:Field数值验证参数总结pydantic 是一个让你能够 confidentl

基于Go语言开发一个 IP 归属地查询接口工具

《基于Go语言开发一个IP归属地查询接口工具》在日常开发中,IP地址归属地查询是一个常见需求,本文将带大家使用Go语言快速开发一个IP归属地查询接口服务,有需要的小伙伴可以了解下... 目录功能目标技术栈项目结构核心代码(main.go)使用方法扩展功能总结在日常开发中,IP 地址归属地查询是一个常见需求:

C#使用SendMessage实现进程间通信的示例代码

《C#使用SendMessage实现进程间通信的示例代码》在软件开发中,进程间通信(IPC)是关键技术之一,C#通过调用WindowsAPI的SendMessage函数实现这一功能,本文将通过实例介绍... 目录第一章:SendMessage的底层原理揭秘第二章:构建跨进程通信桥梁2.1 定义通信协议2.2