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操作完成),则可能需要等待该状态结束后才能退出。

相关推荐
白书宇1 分钟前
13.100ASK_T113-PRO RTC实验
linux·arm开发·驱动开发·嵌入式硬件·物联网·硬件工程
qzWsong10 分钟前
hadoop+wsl 10.255.255.254,BlockMissingException: Could not obtain block: 踩坑
linux·hadoop
草字28 分钟前
uniapp 修改网页标题title
java·服务器·uni-app
清风~徐~来39 分钟前
【Linux】指令 + 压缩与解压
linux·运维·服务器
速盾cdn44 分钟前
速盾:CDN服务器和双线服务器哪个更好?
服务器·网络·安全
学Linux的语莫1 小时前
配置Nginx实现用IP测试灰度发,通过不同用户ID测试灰度发布
linux·运维·服务器·nginx
BlackPercy1 小时前
【ubuntu】Geogebra
java·linux·运维·ubuntu
ichdream1 小时前
【Linux内核深度解析】TCP协议栈之tcp_recvmsg
linux·网络·后端·网络协议·tcp/ip·软件工程
luciferau1 小时前
evbuffer
linux·服务器·网络·c++
BJ_Bonree1 小时前
智能可观测护航“双十一”,电商零售高峰稳健冲刺!
运维