本文主要是介绍Linux第十四章,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux
🔥座右铭:“不要等到什么都没有了,才下定决心去做”
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
僵尸状态(zombie)
孤儿进程
进程优先级
top指令
top修改进程优先级
nice值的范围
进程的其他概念
时间片
电脑在没有联网的情况下关机之后,为什么电脑还能够正确的显示时间?
linux内核支持进程之间进行cpu资源抢占的!
cpu中的寄存器
僵尸状态(zombie)
僵尸进程是指已经终止执行但父进程尚未调用
wait()
或waitpid()
来获取其终止状态的进程。这种状态下,进程已经释放了所有的资源,但其进程描述符仍然存在于系统中,直到其父进程获取了其终止状态后才会被完全清除。僵尸进程通常是由于父进程没有正确处理其子进程的终止状态而导致的。这可能是因为父进程已经退出,但没有释放其子进程的资源,或者是因为父进程忙于其他任务而没有及时处理子进程的终止状态。
你(一般指的是退出进程的父进程,一般父进程是bash,bash广义就是操作系统)怎么知道进程把任务完成的怎么样?
进程退出的时候,要有一些退出信息,表明自己把任务完成的怎么样!(例如,函数中的main函数结尾要return 0)
当一个进程在退出的时候,退出信息会由OS写入到当前退出进程的PCB中,可以允许进程的代码和数据空间释放,但是不能允许进程的pcb被立即释放!!
要让OS或者父进程,读取退出进程的退出信息,得知子进程退出的原因!
进程退出了,但是还没有被父进程或者OS读取,Os必须维护退出进程的pcb结构!!
此时,进程算退出了吗?退出了,因为在内存中代码和数据释放了
此时的状态:Z(zombie僵尸状态)
父进程或者OS读取之后,得知进程退出的原因,PCB状态先被改成X(dead死亡状态)状态,才会被释放
如果一个进程Z状态了,但是父进程就是不释放(回收)他,pcb就要一直存在
如果我们不及时释放他,可能造成内存泄漏
事例
[BCH@hcss-ecs-6176 10_12]$ cat proc.c #include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() {pid_t id=fork();if(id<0)return 0;else if(id==0){//子进程int cnt=5;while(cnt){printf("I am child, run times:%d\n",cnt--);sleep(1);}printf("I am child,dead!:%d\n",cnt--);exit(2);}else{//父进程while(1){printf("I am father,running ang times!\n");sleep(1);}}return 0; }[BCH@hcss-ecs-6176 10_12]$ ./myproc I am father,running ang times! I am child, run times:5 I am father,running ang times! I am child, run times:4 I am father,running ang times! I am child, run times:3 I am father,running ang times! I am child, run times:2 I am father,running ang times! I am child, run times:1 I am father,running ang times! I am child,dead!:0 I am father,running ang times! I am father,running ang times![BCH@hcss-ecs-6176 10_12]$ while :; do ps ajx | head -1&&ps ajx | grep myproc ;sleep 1;echo "##############"; done//每个两秒监视myproc的进程状态PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 9935 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc9935 9936 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc 29420 9940 9939 29148 pts/2 9939 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 9935 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc9935 9936 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc 29420 10000 9999 29148 pts/2 9999 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 9935 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc9935 9936 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc 29420 10037 10036 29148 pts/2 10036 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 9935 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc9935 9936 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc 29420 10097 10096 29148 pts/2 10096 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 9935 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc9935 9936 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc 29420 10157 10156 29148 pts/2 10156 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 9935 9935 2439 pts/0 9935 S+ 1000 0:00 ./myproc9935 9936 9935 2439 pts/0 9935 Z+ 1000 0:00 [myproc] <defunct>//僵尸状态 29420 10210 10209 29148 pts/2 10209 S+ 1000 0:00 grep --color=auto myproc ##############
如果让父进程先退出,子进程不退出
[BCH@hcss-ecs-6176 10_12]$ cat proc.c #include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() {pid_t id=fork();if(id<0)return 0;else if(id==0){//子进程while(1){printf("I am child,running ang times!\n");sleep(1);}}else{//父进程int cnt=5;while(cnt){printf("I am father, run times:%d\n",cnt--);sleep(1);}printf("I am father,dead!:%d\n",cnt--);exit(2);}return 0; }让子进程循环进行,父进程运行5s结束[BCH@hcss-ecs-6176 10_12]$ while :; do ps ajx | head -1&&ps ajx | grep myproc ;sleep 1;echo "##############"; donePPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 18850 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 18850 18851 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 29420 18878 18877 29148 pts/2 18877 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 18850 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 18850 18851 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 29420 18938 18937 29148 pts/2 18937 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 18850 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 18850 18851 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 29420 18975 18974 29148 pts/2 18974 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 18850 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 18850 18851 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 29420 19035 19034 29148 pts/2 19034 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND3218 18850 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 18850 18851 18850 2439 pts/0 18850 S+ 1000 0:00 ./myproc 29420 19095 19094 29148 pts/2 19094 S+ 1000 0:00 grep --color=auto myproc ##############PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND //这里父进程pcb被释放掉了 为什么父进程结束时,进程状态不是z状态,而是直接被释放了呢? 因为父进程的父进程是bash,是OS,OS读取父进程的pcb,立刻就被释放了,所以父进程不是z状态1 18851 18850 2439 pts/0 3218 S 1000 0:00 ./myproc 29420 19132 19131 29148 pts/2 19131 S+ 1000 0:00 grep --color=auto myproc ##############
孤儿进程
父进程不会对孙子进程负责
如果一个进程的父进程直接被释放了(回收),子进程要被pid为1的进程领养,变成孤儿进程
pid为1的进程就是操作系统OS(systemd、initd(老版本))
为什么要领养呢?
因为该进程结束时,需要去读取该进程退出信息
进程优先级
优先级:
排队的本质:就是在确认优先级
优先级是什么:
得到的某种资源的先后顺序
优先级为什么:
本质就是资源不足
优先级怎么做:
其实就是pcb中的一个int字段,数值越小,优先级越高
优先级vs权限
优先级:保证能够得到申请的资源,只不过需要等一等
权限:能还是不能得到某种资源
linux进程的优先级数值范围:60~99
linux中默认进程的优先级都是:80
linux是支持动态优先级调整的
linux进程pcb中存在一个nice值:进程优先级的修正数据
[BCH@hcss-ecs-6176 10_12]$ ps -al F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 R 1000 1354 23327 0 80 0 - 38324 - pts/2 00:00:00 ps 0 S 0 20804 20713 0 80 0 - 40684 poll_s pts/1 00:00:00 top 4 S 0 20886 20696 0 80 0 - 47973 do_wai pts/0 00:00:00 su 4 S 1000 20887 20886 0 80 0 - 28952 do_wai pts/0 00:00:00 bash 0 S 0 22985 22849 0 80 0 - 40684 poll_s pts/3 00:00:00 top 4 S 0 23326 22807 0 80 0 - 47973 do_wai pts/2 00:00:00 su 4 S 1000 23327 23326 0 80 0 - 28952 do_wai pts/2 00:00:00 bash 0 S 1000 30599 20887 0 80 0 - 1054 hrtime pts/0 00:00:00 myprocPRI:进程优先级 NI:nice值 pri(新)=pri(old)+nice old pri(旧的优先级),都是从80开始的
top指令
top是一个常用的 Linux 命令行工具,可以实时动态地监视系统的处理器使用情况、内存使用情况及进程信息等。通过 top 命令,用户可以看到当前的 CPU 占用情况、内存占用情况、进程数量、进程的 PID、用户、内存使用量、CPU 占用率等信息。
top命令默认情况下会按照CPU占用率高低来排序,并实时更新最新的进程信息。在命令行中输入top即可启动top命令,进入Top交互模式。在Top交互模式下,用户可以对top显示的信息进行排序和过滤,以便更好地查看系统状态。
常用的Top命令选项包括:
* -d:指定top刷新的时间间隔,单位为秒
* -u:根据用户名来过滤进程
* -p:根据进程ID来过滤进程
* -H:显示进程的线程信息
除了实时监控进程信息外,top还可以通过按键来进行进程操作,如终止进程、调整进程优先级等。具体操作方式可以在Top交互模式中查看相关帮助信息。
top修改进程优先级
在命令行输入top 输入r:重新调正nice值 PID to renice [default pid = 1]输入需要调整优先级进程的PID PID to renice [default pid = 1] 30599 输入改正的nice值 Renice PID 30599 to value 10[BCH@hcss-ecs-6176 10_12]$ ps -al F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 R 1000 8006 23327 0 80 0 - 38324 - pts/2 00:00:00 ps 0 S 0 20804 20713 0 80 0 - 40684 poll_s pts/1 00:00:01 top 4 S 0 20886 20696 0 80 0 - 47973 do_wai pts/0 00:00:00 su 4 S 1000 20887 20886 0 80 0 - 28952 do_wai pts/0 00:00:00 bash 0 S 0 22985 22849 0 80 0 - 40684 poll_s pts/3 00:00:01 top 4 S 0 23326 22807 0 80 0 - 47973 do_wai pts/2 00:00:00 su 4 S 1000 23327 23326 0 80 0 - 28952 do_wai pts/2 00:00:00 bash 0 S 1000 30599 20887 0 90 10 - 1054 hrtime pts/0 00:00:00 myproc 此时PID为30599进程的优先级改成了90,优先级变低了
如果我们想要把优先级提高,普通用户是无法做的,权限是不够的,我们需要sudo提权
sudo top
nice值的范围
nice调整最小值是:-20,超出部分统一当成-20
nice调整最大值是:19,超出部分统一当成19
nice值的范围:-20~19
为什么要把优先级限定在一定的范围呢??
Os调度进程的时候,较为均衡的让每一个进程都要得到调度
如果优先级被任意修该,会导致:
容易导致优先级较低的进程,长时间得不到CPU资源--饥饿进程,所以会把优先级限制到一定范围
进程的其他概念
竞争性:
系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
独立性:
多进程运行,需要独享各种资源,多进程运行期间互不干扰
并行:
多个进程在多个CPU下分别,同时进行运行,这称之为并行
并发:
多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
注意:一个cpu情况下:在一时刻只能有一个进程在cpu上跑,你看到多个进程在跑(例如,你在玩游戏,又在听歌,又在下载软件…),这是并发
每一个进程不是占有CPU就一直运行,每隔一段时间(时间片),自动从CPU上剥离下来
时间片
在 Linux 中,时间片(Time Slice)是指操作系统给进程分配的 CPU 运行时间。时间片通常以毫秒或微秒为单位,表示进程在 CPU 上运行的时间长度。
在多任务环境中,多个进程同时运行在计算机上,每个进程只能运行一段时间,然后需要让出 CPU 时间片给其他进程运行,这样才能保证所有进程得到相同的 CPU 运行时间。因此,操作系统在调度进程运行时,将时间片分配给每个进程用于执行指令,当时间片耗尽后,操作系统会暂停当前进程的执行,并将 CPU 时间片分配给下一个等待执行的进程。
在 Linux 中,时间片的长度是由调度器来控制的。通过采用不同的调度算法和策略,可以决定进程获得的时间片长度和优先级,从而影响系统的性能和响应速度。
需要注意的是,时间片的大小不是固定的,可以根据实际情况进行动态调整。例如,在实时应用程序中,需要更短的时间片来确保快速响应用户请求,而在后台进程中,可以分配更长的时间片以提高计算效率。因此,在 Linux 中,可以通过调整调度器的参数和策略来实现不同的时间片长度和分配方式。
电脑在没有联网的情况下关机之后,为什么电脑还能够正确的显示时间?
在没有联网的情况下,电脑可以通过硬件上的实时时钟(Real-Time Clock,RTC)来维护并显示时间。实时时钟是一种专门用于追踪时间的硬件设备,它通常由一个电池供电以保持时间的持久性。
当你的电脑关机时,实时时钟仍然运行,并且能够通过电池提供的电源继续工作。实时时钟记录了当前的日期和时间,并将其保存在计算机的 CMOS(Complementary Metal-Oxide-Semiconductor)芯片中。
当你再次打开电脑时,操作系统启动会读取 CMOS 中的时间信息,并将其加载到系统中。因此,即使电脑在关机期间没有连接互联网或获取网络时间服务器的时间同步,它仍然可以正确地显示上一次关机时的时间。
需要注意的是,如果电池电量过低或电池损坏,实时时钟可能会停止工作,导致电脑在关机后无法正确显示时间。此时可能需要更换电池来恢复实时时钟的正常运行。
linux内核支持进程之间进行cpu资源抢占的!
例如,一个优先级为80的进程,正在运行,还没有运行结束,这时需要一个优先级为60的进程运行,此时优先级为80的进程会被强行从cpu上剥离,将优先级为60的进程放在cpu上运行
linux内核是基于时间片的抢占式内核
cpu中的寄存器
CPU(中央处理器)中包含多个寄存器(Registers),它们用来暂存和执行指令、存储数据和地址等重要信息。寄存器是CPU内部的高速存储器,与内存不同,它们位于CPU核心中,可以快速访问,比内存更快。1. 通用寄存器:* 累加器(EAX):用于存放通用数据和运算结果。* 基址寄存器(EBX):通常用于存放内存地址。* 计数器(ECX):可作为循环计数器使用。* 数据寄存器(EDX):用于存放通用数据和运算结果。* 指针寄存器(ESI、EDI):用于源地址和目标地址的指针操作。 2. 特殊目的寄存器:* 栈指针寄存器(ESP):指向当前堆栈的栈顶。* 基址指针寄存器(EBP):在函数调用时用于保存调用者的帧指针。* 指令指针寄存器(EIP):存放下一条将要执行的指令地址。 3. 控制寄存器:* 标志寄存器(EFLAGS):存储处理器状态和标志位,如零标志、进位标志、溢出标志等。* 段寄存器(CS、DS、ES、FS、GS、SS):用于保存段选择子,用于访问内存中的不同段。
事例
Fun() {int a=10;//a是临时变量,是在栈开辟的空间,函数调用结束后,空间会被释放return a;//为什么我们定义的栈临时变量,会返回给外部,实际上是将临时变量的值放到了cpu中eax寄存器中 } int c=fun();为什么我们的程序/进程,他怎么知道我们当前运行到哪里了? cpu内,寄存器eip:程序计数器,存放下一条将要执行的指令地址。
我们进程,在运行的时候,是会使用寄存器的,我们进程会产生各种数据在cpu寄存器上临时保存!
如果我们有多进程呢?各个进程在CPU寄存器中形成的临时数据(进程硬件上下文),都应该是不一样的!!但是cpu寄存器硬件只有1套,各个进程的上下问数据有几套呢?
例如,10个进程,那么上下文数据有10个
寄存器!=寄存器的内容
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸
这篇关于Linux第十四章的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!