【Linux】进程优先级进程切换

ops/2024/10/22 16:33:53/

在这里插入图片描述

文章目录

  • 进程优先级
    • 查看进程优先级
    • 进程优先级的修改
  • 进程切换
    • 进程切换的概念
  • 总结

进程优先级

进程优先级是操作系统中用于决定进程调度顺序的重要属性。它表示一个进程在系统资源分配和 CPU 调度中的相对重要性。优先级越高的进程通常会获得更多的 CPU 时间和资源,从而更快地完成其任务。

查看进程优先级

ps -l

在这里插入图片描述

通常ps -l查询不到我们启动的进程的信息,所以我们一般都是用ps -al查询进程信息。
在这里插入图片描述
可以看到我们启动的myprocess。
这里有两个信息来觉得我们的优先级。
在这里插入图片描述
一个是PRI,一个事NI值,这两个决定了进程的优先级。
最终优先级的计算公式: P R I (最终) = P R I (默认) + N I PRI(最终)=PRI(默认)+NI PRI(最终)=PRI(默认)+NI
NI值也称为nice值,是优先级的修正数据。
这里还有一个比较重要的信息:UID
UID是操作系统中用于唯一标识用户的数字。在Linux中,每个用户都有一个唯一的 UID,用于控制访问权限和资源管理。
这里可以看到myprocess这个进程是由UID是1000的用户启动的。
UID的作用:我们知道Linux中有权限的概念,那么权限是如何实现的呢?其实每个文件也是有UID的。
在这里插入图片描述
当我们用某个指令的时候,比如说touch,mkdir等等指令,操作系统是如何判断是否有权限的呢,因为使用指令实际本质上也是启动一个进程,这个进程势必也是有UID的,所以操作系统可以对比这个文件的UID和这个操作的UID,看这个操作的UID对应的文件是否有这个权限,最后决定是否能进行这个操作。

进程优先级的修改

进程优先级的修改本质上是修改nice值,修改的是优先级修正数据,进而最终影响我们的最终优先级
进程优先级的修改主要有两种:

  1. 指令
  2. 代码

指令修改:
利用top指令修改进程优先级:
在这里插入图片描述
打开top,输入r进入到优先级修改的模式,通过PID来对优先级进行修改,输入我们对应的PID,然后对进程的nice值进行修改。
在这里插入图片描述
可以看见我们的NI值由默认的0修改为了1,最终优先级也是由默认的80,变为了81,这里我们可以知道:
P R I (最终) = P R I (默认 80 ) + N I PRI(最终)=PRI(默认80)+NI PRI(最终)=PRI(默认80+NI

我们可以通过修改进程优先级来确定最终优先级的上限和下限,这里我们不知道最大的NI值是多少,先姑且修改为100.
在这里插入图片描述
可以看见实际的nice值没有修改为100,而是修改为了19,说明nice值的上限是19,最终进程优先级的上限是99,我们继续来确定下限,这里我们也同样用-100,来表示最小nice值。
在这里插入图片描述

可以看见实际的nice也没有被修改为-100,而是被修改为了-20,说明nice值的下限是-20,PRI的下限是60,这里我们就可以确定nice值是[-20,19],40个数,而最终优先级的范围是[60,99]

进程切换

进程切换的概念

进程切换是指操作系统在多个进程之间切换 CPU 的执行权的过程。由于在一个操作系统中,CPU 资源是有限的,而通常会有多个进程需要同时执行,因此操作系统会通过进程切换来实现多任务处理。
当一个进程执行完一个时间片之后,就会执行进程切换,切换到下一个进程,这样循环往复就形成了进程间的轮转调度。
那么进程的切换是如何进行的呢?我们来画一个简图:
我们知道CPU中有很多寄存器,比如:eax,ebx,ecx,edx,eflag,ecs,eds,efs,eip(pc),ir等等。

对于上面这么多寄存器我们只需要知道:
eip(pc):存储当前正在执行的指令的下一条指令的地址的寄存器
ir:指令寄存器,是CPU内部一个专门用于存储当前正在执行的指令的寄存器。它在CPU执行周期中起着关键作用,负责暂时保存从内存中取出的指令,以便CPU解码和执行。

在这里插入图片描述

当程序已经加载到内存当中时,pc开始读取指令,然后ir读取pc存储的地址对应的指令。ir存储完指令之后,会进行解码,然后取操作数等等操作,最后会得到这句代码的结果,但是在ir存储完了之后,pc会根据ir中代码的长度,然后跳到下一个代码首的地址,存储下一个代码首的地址,当CPU执行完了之后就会执行下一句代码。
在这里插入图片描述
起初pc是指向这里的,但是ir读取完了之后,pc会更新。
在这里插入图片描述

p c (下一个) = p c (当前) + i r (对应的代码的长度) pc(下一个)=pc(当前)+ir(对应的代码的长度) pc(下一个)=pc(当前)+ir(对应的代码的长度)
就可以找到下一个代码的首个位置,然后进行循环处理,这时单个时间片处理进程的情况,这下我们加上多个进程处理的情况。
在这里插入图片描述
寄存器中的数据通常被视为临时数据。寄存器用于快速存储和访问CPU在执行指令时所需的操作数、地址、计算结果等信息。由于寄存器的访问速度远快于内存,它们是CPU内部用于临时存储和处理数据的关键部分。
首先我们考虑的是不保护临时数据的情况:
如果我们不保护临时数据,假如当我们执行到code3的时候,一个时间片已经执行完了,所以应该切换到下一个进程的时间片进行执行,执行下一个进程的时间片时,在这里插入图片描述
这时,上一个进程的临时数据已经被第二个进程的数据覆盖掉了,当我们执行到code5的时候,一个时间片已经结束,所以回到第一个进程继续执行下一个时间片,但是上一个进程的临时数据已经被覆盖掉了,这时我们就不知道从哪句代码运行了,所以如果不保护临时数据是不可能形成进程切换,所以肯定有临时数据的保护,当我们一个时间片结束之后,在某个地方保存着这些临时变量,当执行完第一个进程之后保存临时数据,然后执行下一个时间片,执行完一系列时间片之后回到这个这个进程时,将保存起来的临时数据加载到CPU当中重新执行,上个时间片接着的进度。
**进程切换:**当一个进程的时间片结束之后切走到下一个进程,一系列进程完成之后切回到这个进程继续完成。
切走:将相关寄存器内容,保护起来
切回:将历史保存的寄存器数据,恢复到寄存器当中每次切换时。

这些临时数据到底是放在哪里的呢?

	unsigned short uid,euid,suid;unsigned short gid,egid,sgid;unsigned long timeout;unsigned long it_real_value, it_prof_value, it_virt_value;unsigned long it_real_incr, it_prof_incr, it_virt_incr;long utime,stime,cutime,cstime,start_time;unsigned long min_flt, maj_flt;unsigned long cmin_flt, cmaj_flt;struct rlimit rlim[RLIM_NLIMITS]; unsigned short used_math;unsigned short rss;	/* number of resident pages */char comm[16];struct vm86_struct * vm86_info;unsigned long screen_bitmap;
/* file system info */int link_count;int tty;		/* -1 if no tty, so it must be signed */unsigned short umask;struct inode * pwd;struct inode * root;struct inode * executable;struct vm_area_struct * mmap;struct shm_desc *shm;struct sem_undo *semun;struct file * filp[NR_OPEN];fd_set close_on_exec;
/* ldt for this task - used by Wine.  If NULL, default_ldt is used */struct desc_struct *ldt;
/* tss for this task */struct tss_struct tss;
#ifdef NEW_SWAPunsigned long old_maj_flt;	/* old value of maj_flt */unsigned long dec_flt;		/* page fault count of the last time */unsigned long swap_cnt;		/* number of pages to swap on next pass */short swap_table;		/* current page table */short swap_page;		/* current page */
#endif NEW_SWAPstruct vm_area_struct *stk_vma;

上面是PCB原码,内部有一个结构体是tss,我们来看看tss结构体:

struct tss_struct {unsigned short	back_link,__blh;unsigned long	esp0;unsigned short	ss0,__ss0h;unsigned long	esp1;unsigned short	ss1,__ss1h;unsigned long	esp2;unsigned short	ss2,__ss2h;unsigned long	cr3;unsigned long	eip;unsigned long	eflags;unsigned long	eax,ecx,edx,ebx;unsigned long	esp;unsigned long	ebp;unsigned long	esi;unsigned long	edi;unsigned short	es, __esh;unsigned short	cs, __csh;unsigned short	ss, __ssh;unsigned short	ds, __dsh;unsigned short	fs, __fsh;unsigned short	gs, __gsh;unsigned short	ldt, __ldth;unsigned short	trace, bitmap;unsigned long	io_bitmap[IO_BITMAP_SIZE+1];unsigned long	tr;unsigned long	cr2, trap_no, error_code;union i387_union i387;
};

可以看见当中有很多寄存器信息,寄存器当中的临时信息就是存储在PCB当中的tss结构体当中的。
TSS是 x86 架构中的一个重要数据结构,用于管理任务切换。它包含关于当前任务的信息,比如任务的状态、CPU 寄存器、堆栈指针等。

总结

在 Linux 操作系统中,进程优先级和进程切换是确保系统高效运行的核心机制。通过合理设置进程优先级,系统能够根据任务的重要性和紧急性,合理分配 CPU 资源。这不仅提升了系统的响应速度,还能有效避免资源的浪费。

同时,进程切换的实现方式保证了多任务环境下的平稳运行。尽管频繁的进程切换可能会带来一定的性能开销,但通过调度算法的优化,Linux 仍能在保持高效性的同时,确保各个进程得到公平的执行机会。

了解这些概念不仅有助于深入掌握 Linux 系统的工作原理,还能为优化应用程序性能提供指导。希望本文能为你在 Linux 进程管理方面的学习和实践提供一些启发。


http://www.ppmy.cn/ops/127613.html

相关文章

讲一讲Redis五大数据类型的底层实现

讲一讲Redis五大数据类型的底层实现 Redis五大数据类型的底层实现 Redis的五大数据类型分别是字符串(String)、列表(List)、哈希(Hash)、集合(Set)和有序集合(Zset&…

薪资管理系统原型PC端+移动端 Axure原型 交互设计 Axure实战项目

薪资管理系统原型PC端移动端 Salary Management System Prototype 薪资管理系统原型图是一种以图形化方式展示系统界面和功能交互的设计图形。该原型图旨在呈现薪资管理系统的整体架构、界面布局和用户交互流程,为开发团队和利益相关者提供一个清晰而具体的概念。…

ansible————ansible的文件管理

一、ansible文件管理常用的模块 file模块:创建文件/目录,删除/目录文件等 copy模块:将控制节点的文件送到被管理主机上 lineinfile模块:向文件输入内容 stat模块:显示文件的状态信息 fetch模块:从被管理…

Django 获取用户IP

获取代理函数 def get_ip(request):# 判断是否使用代理x_forwarded_for request.META.get(HTTP_X_FORWARDED_FOR)if x_forwarded_for:# 使用代理获取真实的ipip x_forwarded_for.split(,)[0]else:# 未使用代理获取IPip request.META.get(REMOTE_ADDR)return HttpResponse({…

Java高级Day54-正则表达式底层实现

140.正则表达式 正则表达式底层实现 介绍:一个正则表达式,就是用某种模式去匹配字符串的一个公式 public class TestJava {public static void main(String[] args) {String content "11943wd2342drwf4235"; ​//目标:匹配所有…

Element-plus中的表单验证

一、属性绑定 在 Element-plus 的 Form 组件中&#xff0c;需要对用户的输入进行规范验证时&#xff0c;可使用 rules 属性对验证规则做绑定。并在 el-form-item标签上设置 prop 属性的键值。 <template><div><el-form :model"ruleForm"style"…

文本数据可视化

文字是传递信息最常用的载体。在当前这个信息爆炸的时代,人们接收信息的速度已经小于信息产生的速度,尤其是文本信息。当大段大段的文字摆在面前,已经很少有耐心去认真把它读完,经常是先找文中的图片来看。这一方面说明人们对图形的接受程度比枯燥的文字要高很多,另一方面…

物联网之温湿度传感器模块、arduino、esp32

MENU 原理硬件电路设计软件程序设计 原理 无论是工业领域还是日常生活&#xff0c;温度和湿度一直都是两个比较重要的指标&#xff0c;DHT11和DHT22是DHTxx系列中使用最广泛的两种传感器。它们有着相同的引脚&#xff0c;用法一致。 如果拆下传感器的外壳&#xff0c;其实里面…