Runqueue的添加进程,切换进程,退出进程完整过程

一、添加进程

一、进程状态确认

首先,系统需要确认进程的状态。在Linux中,进程有多种状态,如TASK_RUNNING(运行中)、TASK_INTERRUPTIBLE(可中断等待)、TASK_UNINTERRUPTIBLE(不可中断等待)等。只有状态为TASK_RUNNING的进程才会被添加到runqueue中。

二、选择目标runqueue

  1. 负载均衡考虑:为了系统负载的均衡,Linux内核在选择将进程添加到哪个runqueue时会考虑当前各个CPU的负载情况。如果某个CPU的负载较轻,那么新进程更有可能被添加到该CPU的runqueue中。

  2. 优先级匹配:除了负载均衡外,内核还会考虑进程的优先级。每个runqueue都维护了多个优先级队列,内核会根据进程的优先级将其添加到相应的队列中。

三、添加进程至活动队列

  1. 分配task_struct:每个进程在内核中都有一个对应的task_struct结构体,它包含了进程的各种信息,如状态、优先级、调度信息等。在将进程添加到runqueue之前,系统会为其分配一个task_struct结构体。

  2. 链接至活动队列:进程通过其task_struct结构体中的run_list成员链接到runqueue的活动队列中。活动队列维护了正在运行且时间片还没有结束的进程。

四、更新调度信息

  1. 更新bitmap:runqueue中的每个优先级队列都有一个对应的bitmap数组,用于快速判断该队列是否为空。当进程被添加到某个优先级队列时,系统会更新对应的bitmap数组,以反映队列的非空状态。

  2. 调整调度算法:Linux内核采用了多种调度算法,如O(1)调度算法等。在将进程添加到runqueue后,系统会根据当前的调度算法和进程的优先级等信息,调整调度策略,以确保系统的高效运行。

五、等待调度

  1. 等待CPU时间片:一旦进程被添加到runqueue的活动队列中,它就会等待CPU的调度。当CPU空闲或当前运行的进程时间片耗尽时,调度器会从活动队列中选择一个优先级最高的进程来运行。

  2. 状态切换:当进程被调度运行时,其状态会从TASK_RUNNING(或其他等待状态)切换为实际运行状态,并开始在CPU上执行。

六、时间片耗尽与队列切换

  1. 时间片耗尽:如果进程的时间片耗尽而还没有完成执行,那么它会被从活动队列中移出,并添加到过期队列中。过期队列中的进程已经耗尽了它们的时间片,等待下次被调度。

  2. 队列切换:当活动队列中的所有进程都被调度完后,系统会交换活动队列和过期队列的指针,使原来的过期队列成为新的活动队列,并继续调度其中的进程。

二、进程切换

在Linux系统中,由于CPU资源有限,而进程数量众多,因此需要通过调度算法来合理地分配CPU时间给各个进程。runqueue就是这样一个用于管理和调度可运行进程的队列。当进程的时间片用完或遇到其他需要调度的条件时,就会发生进程切换。

一、进程切换的具体流程

1. 触发调度:

• 当进程的时间片用完、进程被阻塞、新进程被创建或唤醒,以及系统负载均衡等情况下,会触发调度器进行进程切换。

2. 选择下一个进程:

• 调度器会根据进程的优先级、调度策略(如CFS完全公平调度算法、RT实时调度算法等)以及当前系统的负载情况,从runqueue中选择一个合适的进程来运行。

3. 保存当前进程的状态:

• 在切换进程之前,系统会保存当前进程的状态,包括CPU寄存器中的值、进程的内存地址空间等。这些信息会被保存在进程的task_struct结构体中的相应字段里。

4. 更新调度信息:

• 系统会更新runqueue中的相关调度信息,如bitmap数组,以反映当前各个优先级队列的状态。

5. 切换进程上下文:

• 进程上下文切换是进程切换的核心步骤。它涉及两个主要部分:进程地址空间切换和处理器状态切换。

• 进程地址空间切换:将下一个进程的虚拟地址空间转换为物理地址空间,并设置到CPU的页表基址寄存器中。这样,当进程访问用户空间地址时,MMU(内存管理单元)会通过这个寄存器来遍历页表,获得物理地址。

• 处理器状态切换:保存当前进程的处理器状态(如寄存器值、程序计数器PC等),并恢复下一个进程的处理器状态。这包括将下一个进程的task_struct地址存放在特定的寄存器中,以便通过current宏找到当前进程。

6. 开始执行下一个进程:

• 完成上下文切换后,CPU开始执行下一个进程。此时,该进程成为当前进程,并继续其之前的执行或开始新的执行。

二、进程切换的注意事项

  1. 效率:进程切换是一个开销较大的操作,因为它涉及大量的上下文保存和恢复工作。因此,系统需要尽量减少不必要的进程切换,以提高整体性能。

  2. 公平性:调度器需要确保所有进程都能公平地获得CPU时间,避免某些进程长时间占用CPU而其他进程得不到执行。

  3. 实时性:对于实时系统来说,进程切换的延迟需要尽可能小,以满足实时任务的时间要求。

进程在Linux内核的runqueue(运行队列)中的退出流程是一个涉及多个步骤和组件的过程。以下是对该流程的具体描述:

三、进程退出

一、进程退出的触发条件

进程退出可以由多种情况触发,包括但不限于:

  1. 进程正常结束:进程完成了其执行的任务,通过调用exit()函数或从main函数返回等方式正常退出。

  2. 进程异常终止:进程由于接收到终止信号(如SIGKILL、SIGTERM等)而异常退出。

  3. 进程被父进程回收:在父进程调用wait()或waitpid()等系统调用时,子进程结束运行并被父进程回收。

二、进程退出时的资源释放

在进程退出之前,系统会释放该进程所占用的系统资源,这包括:

  1. 关闭文件描述符:释放进程打开的文件资源,确保文件句柄被正确关闭。

  2. 释放内存:回收进程申请的内存空间,包括堆内存、栈内存以及数据段等。

  3. 其他资源:如信号量、消息队列、管道等进程间通信资源也会被释放。

三、进程从runqueue中移除

当进程准备退出时,它需要从runqueue中被移除。这通常涉及以下步骤:

  1. 更新runqueue状态:将进程从runqueue的活动队列(如果它在那里)或过期队列(如果它因为时间片耗尽而被移动到这里)中移除。

  2. 调整调度器状态:由于进程的退出,调度器可能需要调整其内部状态,如更新优先级队列的bitmap数组等。

四、进程退出后的处理

进程退出后,系统还需要进行一些后续处理,包括:

  1. 更新进程状态:将进程的状态设置为TASK_DEAD(或类似的表示进程已死的状态)。

  2. 通知父进程:如果进程是子进程,系统会向其父进程发送SIGCHLD信号,通知父进程子进程已结束。

  3. 回收进程资源:最终,系统会回收进程的所有资源,并将其从系统中完全移除。这包括释放task_struct结构体等内核数据结构所占用的内存。

五、特殊情况的处理

在多线程环境中,进程的退出还涉及线程的管理。如果进程中的某个线程调用exit()函数退出,整个进程(线程组)都会退出。此时,系统会向进程中的其他线程发送终止信号,并尝试唤醒它们以处理信号并退出。如果线程在不可中断的等待状态(如等待I/O操作完成),则可能需要等待该状态结束后才能退出。

相关推荐
大树883 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质4 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush44 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5204 小时前
Linux 11 动态监控指令top
linux
小宇宙Zz4 小时前
Maven依赖冲突
java·服务器·maven
Inhand陈工5 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智5 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
不会C语言的男孩5 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
shushangyun_5 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化