0
点赞
收藏
分享

微信扫一扫

HTML输出特殊字符详细方法

栖桐 2023-12-22 阅读 35
linux

🌟前言

        本篇博客基于学习完冯诺依曼体系结构与操作系统及其进程,进一步深度理解进程,学习完本篇对进程的理解会更上一层楼,想必大家已经按耐不住接收新的知识,那咱们话不多说进入今天的主题--->【Linux】进程状态、进程优先级和进程切换😳😳。

⭐主体

我们从以下学习【Linux】进程状态、进程优先级和进程切换🤗🤗。

🌙操作系统进程

        由于Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态。

        进程状态:一个程序被加载到内存变成进程之后,操作系统要对该进程进行管理,即为其创建对应的PCB对象,而进程状态,本质上就是PCB内部的一个整形变量,不同的整形值就对应不同的进程状态。

        常见的进程状态:运行、挂起、阻塞、新建、就绪、等待、挂机、死亡。进程的不同状态本质都是用来满足不同的运行场景的。

🌙Linux进程状态

我们Linux进程状态,可以用kernel源代码查看:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
  • R运行状态(running) : 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
  • z僵尸状态(zombie):这个状态是一个已经运行完的子进程等待父进程回收它的返回信息。
     

那么我们可以亲自操作来查看各种状态

ps aux / ps axj //命令

那咱们看看Linux各种状态下的样子:

💫R运行状态 

创建Makefile:

创建myprocess.c:

#include<stdio.h>
#include<unistd.h>

int main()
{
	while(1);
	{
		int a = 0;
        a = 1+1;
	}
	return 0;
}

这里博主没有显示,因为没有运行。

💫S睡眠状态 

 创建Makefile:

创建myprocess.c:

#include<stdio.h>
#include<unistd.h>

int main()
{
	while(1);
	{
		int a = 0;
        a = 1+1;
	}
	return 0;
}

🌙两个特殊进程

进程退出的时候不能立即释放该进程对应的资源!保存一段时间,让对应的父进程/操作系统进行读取。

💫僵尸进程 

        进程退出了,但退出信息没有父进程或者OS被回收,那么此时该进程就处于僵尸进程。咱们演示一下效果。

创建myproc.c:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
    pid_t id = fork();
    if(id == 0)
    {
       // 子进程
            printf("after fork, 我是子进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
	    sleep(5);
	    exit(1);
    }
    else{
        // 父进程
        while(1){
            printf("after fork, 我是父进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
            sleep(1);
        }
    }
    return 0;
}

创建Makefile:

myproc:myproc.c
	gcc -o myproc myproc.c

.PHONY:clean

clean:
	rm -f myproc.c

运行结果:

💫孤儿进程 

父进程先退出,子进程就称之为"孤儿进程"

创建myproc.c:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    printf("before fork: I am a prcess, pid: %d, ppid: %d\n", getpid(), getppid());

    sleep(5);
    printf("开始创建进程啦!\n");
    sleep(1);
    pid_t id = fork();
    if (id < 0) return 1;
    else if (id == 0)
    {
       //  子进程
        while (1) {
            printf("after fork, 我是子进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
            sleep(1);
        }
    }
    else {
       //  父进程
        while (1) {
            printf("after fork, 我是父进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
            sleep(1);
        }
    }
    return 0;
}

创建Makefile:

myproc:myproc.c
	gcc -o myproc myproc.c

.PHONY:clean

clean:
	rm -f myproc.c

运行结果:

🌙进程优先级

💫优先级概念

  • 优先级

即获取资源的先后顺序和先后被执行的能力。优先级高的先获得和执行,优先级低的反之。
存在的原因:资源太少,需要资源分配。

  • Linux优先级

优先级本质就是PCB里面一个整数数字(或者几个整型数字)

Linux优先级有一个特点:很快

💫查看系统进程

在linux或者unix系统中,用ps –l/ps -al命令则会类似输出以下几个内容:

💫PRI和NI

Linux中由两个整型数字决定优先级:PRI(priority)和NI(nice)

注意:

        Linux下的老的优先级PRI默认值是80!而NI取值是有范围,取值范围是[-20,19]。也就意味着优先级是有取值范围的[80-21,80+19]

        在Linux下支持进程在运行中进行优先级调整的,调整的策略就是更改nice完成的,也就是说会受到nice值影响(但是一般情况下不修改),但是大部分情况下,nice值是默认的也就是0。

这里的PRI优先级是80,NI值是0

💫top命令更改nice

步骤1:sudo top

步骤2:进入top后输入r然后在输入进程的pid(进入进程)输入要修改nice的值

myproc.c代码:

初始NI和PRI:

用top命令进行修改:(先输入命令sudo top后在输入r,在输入进程的PID):

开始修改:(找到进程编号)

看到这个界面就可以开始更改NI值了:

这里博主就不修改了,但是要注意一些细节:

💫特性

这里的独立性对于父进程和子进程是否还是存在?yes

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        while (1)
        {
            printf("this is child process,pid: %d,ppid:%d\n", getpid(), getppid());
            sleep(1);
            int* p = NULL;
            *p = 100;//野指针
        }
    }
    else
    {
        while (1)
        {
            printf("this is parent process,pid:%d,ppid:%d\n", getpid(), getppid());
            sleep(1);
        }
    }
}

运行结果:

子进程崩溃并没有影响父进程。

💫进程切换

  • 1.并发
  • 2.进程如何切换

而进程运行的时候一定会产生很多的临时数据,但这些临时数据只属于当前进程,虽然CPU内部只有一套寄存器硬件,但是寄存器保存的数据只属于当前进程,也就是说,寄存器硬件不是寄存器内的数据,这是两码事,寄存器被所有进程共享,但是寄存器里的数据时每个进程各自私有的。

时间片引出:

  • 进程在运行的时候占有CPU,但是却不是一直占有到进程结束,进程都有自己的时间片!因为时间片的存在,进程会出现没有被执行完就被拿下去的情况,这时候问题来了:这个进程下一次如何在次回到CPU继续运行:
  • 进程切换的时候,需要先进行上下文保护,这里的上下文指的是CPU里的寄存器的数据,而不是寄存器,这里简单理解为临时数据保存至PCB里,而当进程恢复运行的时候,要进行上下文的恢复,该进程在次回到CPU继续运行时,重新加载恢复这些数据。

 🌟结束语

       今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

举报

相关推荐

0 条评论