-
1. 查看进程的调度信息可以使用命令 `ps -eLf` 或 `top`。这些命令可以显示进程的详细信息,包括调度相关的信息。
2. 查看CFS(Completely Fair Scheduler)的调度信息可以使用 `schedstat` 工具。通过 `/proc` 文件系统可以查看,例如使用命令 `cat /proc/schedstat` 可以显示当前CFS的统计信息。
3. 查看调度域的拓扑关系可以使用 `lscpu` 命令。这个命令会显示有关CPU架构的信息,包括调度域的拓扑结构。
4. 在一个双核处理器系统中,假设在Shell界面下运行test程序,CPU0的就绪队列中有4个进程,而CPU1的就绪队列中有1个进程,test程序和这5个进程的nice值都为0。现在来画出test程序在内核空间的运行流程:
```
+---------------------------------------------+
| |
| 用户空间 |
| |
+---------------------------------------------+
| 内核空间 |
| |
| +---------------------------------+ |
| | | |
| | Scheduler (调度器) | |
| | | |
| +---------------------------------+ |
| | | |
| | test程序 | |
| | (PID: X) | |
| | | |
| +---------------------------------+ |
| | | |
| | 进程1 (PID: Y) | |
| | | |
| +---------------------------------+ |
| | | |
| | 进程2 (PID: Z) | |
| | | |
| +---------------------------------+ |
| | | |
| | ... | |
| | | |
| +---------------------------------+ |
+---------------------------------------------+
```
随着时间的推移,CPU0和CPU1的就绪队列可能发生变化,具体的变化取决于调度算法和各个进程的状态。例如,某些进程可能被调度到CPU0或CPU1上执行,而有些进程可能被移出就绪队列,等等。
-
1. 进程是计算机中正在执行的程序的实例。它包含了程序的代码、数据和进程控制块等信息。每个进程都是独立运行的,拥有自己的地址空间、资源和状态。多个进程可以同时运行在计算机系统中,彼此之间相互独立。
2. 操作系统描述和抽象一个进程通过进程控制块(Process Control Block,PCB)来实现。PCB是操作系统维护的一个数据结构,包含了进程的重要信息,如进程状态、程序计数器、寄存器状态、内存分配信息、打开文件的列表等。PCB允许操作系统管理和控制每个进程的执行。
3. 进程有生命周期,包括创建、就绪、运行、阻塞、唤醒和终止等阶段。这些阶段描述了进程从被创建到运行,再到结束的整个过程。
4. 进程通过唯一的进程标识符(Process ID,PID)来进行标识。PID是一个整数,用于唯一地区分系统中运行的每个进程。
5. 进程之间可以有不同的关系,包括父子关系、兄弟关系等。进程之间可以通过进程间通信(IPC)的机制来进行数据交换和协作。
6. 在Linux系统中,第0个进程是"swapper"或"init"进程,其PID为0。这个进程是系统启动时创建的,它在系统初始化期间负责一些基本的初始化工作,并在系统启动后演变为init进程。
7. 在Linux系统中,第1个进程是init进程,其PID为1。init是用户空间的第一个进程,负责系统的初始化和启动用户空间的其它进程。
8. - `fork()`: 创建一个子进程,子进程复制了父进程的地址空间,但是在独立的进程空间中运行。子进程和父进程是独立的,各自有自己的数据和代码副本。
- `vfork()`: 类似于fork,但是在子进程中运行时,它共享父进程的地址空间,直到调用exec或者exit。vfork用于创建一个新进程,但子进程会借用父进程的内存空间,因此在子进程中对内存的修改可能影响到父进程。
- `clone()`: 具有更灵活的选项,可以控制新进程与父进程共享的资源,包括文件描述符、信号处理等。clone更为通用,可以实现类似于fork和vfork的功能,还可以创建线程。
-
1. 进程优先级、nice值和权重之间的关系:
- 进程优先级:操作系统为了有效地调度进程而引入的概念,通常表示为一个数字,数字越低表示优先级越高。
- nice值:是一个用户可调整的进程优先级的参数,范围一般为-20到+19。负值表示高优先级,正值表示低优先级。
- 权重:Linux中的CFS(完全公平调度器)使用权重来确定进程的相对优先级。CFS把进程的nice值转换为一个权重,通过这个权重来分配CPU时间。
具体关系如下:nice值的改变会影响进程的权重,而权重决定了进程在CFS中的调度优先级。较高权重的进程更容易获得CPU时间,从而提高其执行优先级。
2. CFS(完全公平调度器)的工作原理:
- CFS旨在提供公平的CPU时间分配,确保所有运行中的进程都有相等的时间片。
- CFS使用虚拟运行时间(vruntime)来衡量进程的执行时间。每个进程都有一个vruntime值,表示它在CPU上运行的时间。
- 进程的调度优先级与其vruntime值成反比。vruntime值越小,表示进程执行时间越长,其调度优先级越低。
- CFS通过不断选择vruntime最小的进程来进行调度,以确保资源公平地分配。
3. CFS中vruntime的计算:
- 初始时,每个进程的vruntime值为0。
- 当一个进程在CPU上运行时,其vruntime值会增加,增加的速度与进程的权重成正比。
- CFS会根据进程的权重和运行时间来计算新的vruntime值,以维持公平调度。
- 具体计算公式:新的vruntime = 当前vruntime + 运行时间 * 权重。
通过这种方式,CFS通过动态调整vruntime值来确定下一个应该被调度的进程,以实现公平的CPU时间分配。
-
1. Linux内核的内存管理模块主要对以下几类页面进行统计:
- **活动页面(Active Pages)**:正在使用或者最近被使用过的页面。
- **非活动页面(Inactive Pages)**:最近没有被使用过的页面,但仍然在内存中,因为系统认为可能会再次被使用。
- **自由页面(Free Pages)**:完全空闲的页面,可以直接分配给新的数据。
- **缓冲区页面(Buffer Pages)**:被用作文件系统缓存的页面。
- **缓存页面(Cached Pages)**:被高速缓存子系统用来缓存块设备数据的页面。
- **不可交换页面(Unswappable Pages)**:不能被交换到磁盘上的页面。
- **可交换页面(Swappable Pages)**:可以被交换到磁盘上的页面。
2. `/proc/meminfo` 文件提供了有关系统内存使用情况的详细信息。以下是一些常见条目的含义:
- **MemTotal**:系统总内存大小。
- **MemFree**:未被使用的内存大小。
- **MemAvailable**:可用于新进程或文件系统缓存的内存大小。
- **Buffers**:用作块设备缓存的内存大小。
- **Cached**:用作页面缓存的内存大小。
- **SwapCached**:被交换到磁盘上的页面的大小。
- **Active**:正在使用的页面的大小。
- **Inactive**:最近未使用的页面的大小。
- **SwapTotal**:交换空间总大小。
- **SwapFree**:未被使用的交换空间大小。
3. `/proc/meminfo` 中的 `MemTotal` 不等于 QEMU 虚拟机中分配的内存大小可能是因为 QEMU 可能分配了更多的内存给虚拟机,包括一些用于虚拟化和管理的内存。此外,还有一些内核和系统使用的内存,不会被列在 `/proc/meminfo` 中的特定条目中。因此,虚拟机中分配的总内存可能包含一些不在 `/proc/meminfo` 中显示的其他内存开销。
-
1. **_refcount和_mapcount的区别:**
- `_refcount`: 用于跟踪页面的引用计数,表示有多少个指针指向该页面。
- `_mapcount`: 用于跟踪页面在页表中的映射计数,表示有多少个页表项映射到该页面。
2. **匿名页面和高速缓存页面的区别:**
- **匿名页面:** 这是指不与文件关联的页面,通常用于进程的堆栈、匿名映射等。
- **高速缓存页面:** 这是指与文件关联的页面,从文件系统中读取数据,例如文件映射。
3. **trylock_page()和lock_page()的区别:**
- **trylock_page():** 尝试获取页面锁,如果获取成功返回真,否则立即返回假,而不会阻塞。
- **lock_page():** 获取页面锁,如果无法获取,则会阻塞直到锁可用。
4. **page数据结构中flags成员的布局示意图:**
```
+---------------------+
| flags |
+---------------------+
```
5. **_refcount和_mapcount计数的使用案例:**
- **_refcount使用案例:**
- 在内存管理中,通过引用计数来追踪页面的引用,确保在没有引用时可以释放页面。
- 在共享内存机制中,跟踪共享内存块的引用计数。
- **_mapcount使用案例:**
- 在分页系统中,用于跟踪页面在页表中的映射次数,以确保在不再映射时可以释放页面。
- 在内存映射文件时,跟踪页面在文件映射中的映射次数。
-
1. **Linux内核中的页面分配器(page allocator)在理想情况下是如何分配连续物理页面的:**
- 当内核需要分配一定数量的页面时,它会尝试在系统的物理内存中找到一块连续的空闲内存。这通常是通过 Buddy 系统来管理的。
- Buddy 系统将内存划分为不同大小的块,每个块大小都是2的幂次方。当需要分配一定数量的页面时,页面分配器会寻找最小的可用块,并将其划分为所需大小的页面块。
- 如果找到了足够大的连续块,页面分配器将其标记为已用,并返回分配的页面的首地址。
- 如果找不到足够大的连续块,分配器可能会尝试合并相邻的空闲块,以满足分配请求。
2. **确定可以从哪些zone中分配内存的分配掩码(gfp_mask):**
- `gfp_mask` 是一个掩码,用于指定内存分配的一些属性。其中的 `__GFP_BITS_MASK` 部分包含了有关分配的 zone 信息。
- Zone 表示系统中内存的不同区域,通常包括 NORMAL、DMA、HIGHMEM 等。通过在 `gfp_mask` 中设置不同的标志位,可以指定允许从哪些 zone 中分配内存。例如,`GFP_DMA` 表示只能从 DMA 区域分配内存。
3. **页面分配器按照什么方向来扫描zone:**
- 页面分配器通常按照从高地址到低地址的方向来扫描 zone。这是因为在 32 位系统中,内核通常将低地址的内存留给用户空间,而将高地址的内存用于内核空间。
4. **为用户进程分配物理内存时,应该选用GFP_KERNEL还是GFP_HIGHUSER_MOVABLE:**
- 一般情况下,为用户进程分配物理内存时,应该选择 `GFP_KERNEL`。这是因为 `GFP_KERNEL` 表示内核常规的内存分配,适用于大多数内核模块和数据结构。
- `GFP_HIGHUSER_MOVABLE` 主要用于分配用户进程中的可移动内存,例如用于页交换或内存迁移。这个标志用于告诉页面分配器,内核希望尽量在可移动内存区域分配页面。通常,对于普通用户进程的一般内存分配,使用 `GFP_KERNEL` 是更合适的选择。
-
1. **UMA(Uniform Memory Access)和NUMA(Non-Uniform Memory Access)的区别:**
- UMA:在UMA架构中,所有处理器对内存的访问时间是相同的,即内存对所有处理器都是均匀可访问的。这种结构适用于小型系统,其中处理器数量有限。
- NUMA:在NUMA架构中,处理器与内存之间的访问时间可能不同。系统中有多个节点(Node),每个节点有自己的本地内存,而访问本地内存的速度要快于访问远程节点的内存。NUMA适用于大型多处理器系统,其中处理器数量较多。
2. **CPU访问各级存储结构的速度是否一样?**
不同级别的存储结构访问速度是不同的。通常,从快到慢的顺序是:寄存器 > 缓存 > 内存 > 硬盘。寄存器位于CPU内部,速度最快,而硬盘则是机械式存储,速度相对较慢。因此,CPU访问寄存器的速度最快,而访问其他层次的存储结构速度逐渐降低。
3. **内存管理常用的数据结构关系图:**
```lua
+-------------+ +-------------+ +-------------+ +-------------+
| mm_struct | ------->| VMA || Page || PTE |
+-------------+ +-------------+ +-------------+ +-------------+
| | | |
| | | |
V V V V
+-------------+ +-------------+ +-------------+ +-------------+
| vaddr | | paddr | | PFN | | zone |
+-------------+ +-------------+ +-------------+ +-------------+
| |
V V
+-------------+ +-------------+
| pg_data | | ...
+-------------+ +-------------+
```
- **mm_struct(Memory Management Structure)**:表示一个进程的内存空间,包含该进程的所有VMA。
- **VMA(Virtual Memory Area)**:表示一个连续的虚拟内存区域,包含了一段地址范围及其属性。
- **vaddr(Virtual Address)**:虚拟地址,进程中使用的地址。
- **paddr(Physical Address)**:物理地址,实际硬件上的地址。
- **Page**:页,内存管理的最小单位。
- **PFN(Page Frame Number)**:页框号,用于标识内存中的页。
- **PTE(Page Table Entry)**:页表项,用于将虚拟地址映射到物理地址。
- **zone**:表示一块具有相似特性的物理内存。
- **pg_data**:表示一组内存页的集合,包括与该组相关的信息。
这些数据结构之间的转换关系涉及虚拟地址到物理地址的映射、页表的建立和管理,以及对内存的分区和管理。详细的转换关系取决于操作系统的实现和架构。
-
个人信息无误,确认可以完成评测计划
-
1. **ARM64处理器中的两个页表基地址寄存器TTBR0和TTBR1:**
- **TTBR0:** 用于用户态的页表基地址。
- **TTBR1:** 用于内核态的页表基地址。
处理器在运行时根据当前的运行模式(用户态或内核态)选择使用相应的寄存器。在用户态运行时,处理器使用TTBR0中的页表基地址来访问页表,而在内核态运行时,使用TTBR1中的页表基地址。
2. **ARM64处理器的4级页表映射过程:**
- **L0:** 位[47:39],512 GB的大页表。
- **L1:** 位[38:30],1 GB的大页表。
- **L2:** 位[29:21],2 MB的大页表。
- **L3:** 位[20:12],4 KB的页表。
地址位[47:39]决定L0页表项的索引,[38:30]决定L1页表项的索引,以此类推。每个级别的页表项包含下一级页表的基地址。通过递归地查找各级页表项,最终找到对应的物理页框。
3. **判断页表项是块类型还是页表类型:**
- 在L0~L2页表项中,可以通过检查描述符的一些位来确定是块类型还是页表类型。
- 对于块类型(大页表),一般会设置一个特定的标志位,例如在L1和L2级别,ARM64中的"Block"标志位(位1)用于指示块类型。
- 如果标志位设置为1,表示这个页表项是一个块,而不是指向下一级页表的地址。如果标志位为0,表示这是一个页表项,需要继续查找下一级页表。
4. **ARM64 Linux内核中的用户空间和内核空间划分:**
- ARM64采用了经典的Linux内核和用户空间分离的内存管理模型。
- 用户空间的虚拟地址范围通常在0x0000000000000000到0x00007fffffffffff,高47位为0。
- 内核空间的虚拟地址范围通常在0xffff800000000000到0xffffffffffffffff,高47位为1。
- 这样的划分允许内核和用户空间各自有独立的地址空间,提高了系统的稳定性和安全性。在ARM64上,这种分割是通过使用TTBR0和TTBR1寄存器来实现的。 TTBR0用于用户空间,而TTBR1用于内核空间。
-
1. **RISC和CISC的区别:**
- **RISC(Reduced Instruction Set Computing):**
- 简化指令集,指令长度一致。
- 指令执行时间相对较短。
- 采用硬件流水线,提高指令流水线效率。
- 通常具有更多通用寄存器。
- 指令以较低层次的操作为主,需要更多的指令完成同样的任务。
- **CISC(Complex Instruction Set Computing):**
- 复杂指令集,指令长度不一致。
- 单条指令可能执行多个低层次的操作,执行时间较长。
- 通常具有较少的通用寄存器。
- 可能包含一些复杂的指令,减少编程过程中的指令数目。
2. **大小端字节序处理器的存储方式:**
- 对于数值0x1234 5678:
- 大端字节序:0x12 0x34 0x56 0x78
- 小端字节序:0x78 0x56 0x34 0x12
3. **存储读写指令的执行全过程(以双核Cortex-A9为例):**
- 取指令(Instruction Fetch):从内存中读取指令。
- 指令译码(Instruction Decode):解释指令的含义。
- 执行(Execution):执行指令的操作,可能包括运算、数据传送等。
- 访存(Memory Access):如果涉及内存操作,进行读写内存。
- 写回(Write Back):将执行结果写回寄存器。
- 更新程序计数器(PC):指向下一条指令。
4. **内存屏障的产生原因:**
- 多核处理器中存在缓存一致性问题,不同核的缓存可能包含相同的数据,但数据更新时可能不同步。内存屏障用于指导编译器和处理器在代码中插入同步点,确保内存操作的顺序性和可见性。
5. **ARM的内存屏障指令:**
- ARM有三条内存屏障指令:DMB(Data Memory Barrier)、DSB(Data Synchronization Barrier)、ISB(Instruction Synchronization Barrier)。
- 区别在于它们对不同类型的数据访问和指令执行提供了不同级别的同步保障。
6. **高速缓存的工作方式:**
- 缓存存储频繁访问的数据,减少对主存的访问次数。
- 分为缓存行,每行包含多个字节。
- 缓存具有读取和写入操作,读取时检查缓存是否包含所需数据,写入时更新缓存并标记为脏(dirty)。
- 缓存采用替换算法,根据缓存映射方式确定替换规则。
7. **高速缓存映射方式:**
- **全关联(full-associative):** 允许任何主存块映射到任何缓存行。
- **直接映射(direct-mapping):** 每个主存块只能映射到一个特定的缓存行。
- **组相联(set-associative):** 介于全关联和直接映射之间,主存块映射到一组缓存行,选择替换时在该组内选择。
- **为什么使用组相联的高速缓存映射方式:**
- 组相联兼顾了全关联和直接映射的优点,减少了缓存冲突,提高了命中率。
- 更好地平衡了复杂性和性能,适应了多核处理器的需求,降低了替换开销。
-
个人信息无误,确认可以完成阅读计划和打卡任务地址帮我小区后面加2-601,不加也没事