• [Linux](6)进程的概念,查看进程,创建子进程,进程状态,进程优先级


    进程概念

    • 进程是正在运行的程序的实例,它由程序数据进程控制块三部分组成。
    • 进程信息被放在进程控制块中,简称PCB(process control block)
    • Linux操作系统下的PCB是: task_struct ,它是一种结构体。
    • 所有运行在系统里的进程都以 task_struct 链表的形式存在内存中,程序的代码和数据也会被加载到内存中。

    其实计算机管理硬件的一个方法就是先描述,再组织。用struct描述被管理的对象,用特定的数据结构再组织起来。

    task_struct 内容分类

    • 标识符:描述本进程的唯一标识符,用来区别其他进程。
    • 状态:任务状态,退出代码,退出信号等。
    • 优先级:相对于其他进程的优先级。
    • 程序计数器:程序中即将被执行的下一条指令的地址。
    • 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块指针。
    • 上下文数据:进程执行时,CPU 寄存器中的数据
    • I / O 状态信息:包括显示的 I / O 请求,分配给进程的 I / O 设备和被进程使用的文件列表。
    • 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
    • 其他信息

    查看进程

    一、

    显示所有进程

    ps ajx
    
    • 1

    我们也可以先写一个 c 程序

    #include 
    #include 
    
    int main()
    {
        while (1)
        {
            printf("I am a process\n");
            sleep(1);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行起来之后,右击选项卡,选择复制SSH渠道

    在新的终端中使用 ps ajx | grep 'mytest' 可以找到自己的这个进程

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ps ajx | grep 'mytest'
     2888 25600 25600  2888 pts/0    25600 S+    1001   0:00 ./mytest
    25432 28960 28959 25432 pts/1    28959 S+    1001   0:00 grep --color=auto mytest
    
    • 1
    • 2
    • 3

    但是这里显示了两行,第一行当然是我们自己写的程序,第二行的是 grep 命令执行的进程。


    每个进程在系统中,都会存在一个唯一的标识符,称为 pid

    通过下面的指令可以查看pid:

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
     2888 25600 25600  2888 pts/0    25600 S+    1001   0:00 ./mytest
    
    • 1
    • 2
    • 3

    head -1 显示第一行(表头),&& 相当于逻辑与,前面的指令执行成功就执行后面的指令,后面就是找到 mytest 进程,去掉 grep 命令执行的进程。


    二、

    /proc 下,实时存在着当前的进程信息:

    通过 pid 可以找到某个进程,比如 25600 是我们 mytest 程序的进程:

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ls /proc/25600
    attr        coredump_filter  gid_map    mountinfo   oom_score      sched      statm
    autogroup   cpuset           io         mounts      oom_score_adj  schedstat  status
    auxv        cwd              limits     mountstats  pagemap        sessionid  syscall
    cgroup      environ          loginuid   net         patch_state    setgroups  task
    clear_refs  exe              map_files  ns          personality    smaps      timers
    cmdline     fd               maps       numa_maps   projid_map     stack      uid_map
    comm        fdinfo           mem        oom_adj     root           stat       wchan
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这之中可以看到 cwd 就是该进程当前的工作路径,exe 就是进程对应的可执行程序的磁盘文件:

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ls -al /proc/25600
    total 0
    //...
    
    lrwxrwxrwx   1 CegghnnoR CegghnnoR 0 Aug 12 17:35 cwd -> /home/CegghnnoR/code/2022_8_12
    -r--------   1 CegghnnoR CegghnnoR 0 Aug 12 19:58 environ
    lrwxrwxrwx   1 CegghnnoR CegghnnoR 0 Aug 12 17:35 exe -> /home/CegghnnoR/code/2022_8_12/mytest
    
    //...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    通过系统调用获取标识符pid/ppid

    系统调用和库函数的概念

    在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
    系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。


    getpid 获取当前进程的 pid,头文件

    #include 
    #include 
    #include 
    
    int main()
    {
        while (1)
        {
            printf("I am a process, pid:%d\n", getpid());
            sleep(1);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ./mytest
    I am a process, pid:3997
    I am a process, pid:3997
    //...
    
    • 1
    • 2
    • 3
    • 4

    要杀掉该进程,除了使用 ctrl+c,也可以使用 kill -9 [pid]


    使用 getppid 可以获取父进程id(ppid)

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ./mytest
    I am a process, pid:6008, ppid:4583
    ^C
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ./mytest
    I am a process, pid:6023, ppid:4583
    ^C
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ./mytest
    I am a process, pid:6040, ppid:4583
    ^C
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ./mytest
    I am a process, pid:6042, ppid:4583
    ^C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    每次启动进程,pid都会发生变化,ppid不变。

    因为几乎我们在命令行上所执行的所有的指令,都是 bash 进程的子进程。

    代码创建子进程 fork()

    #include 
    #include 
    
    int main()
    {
        pid_t id = fork();
        printf("hello world id:%d\n", id);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结果:

    hello world id:6243
    hello world id:0
    
    • 1
    • 2

    printf执行了两次,id为0的是子进程,>0的是父进程。

    #include 
    #include 
    
    int main()
    {
        pid_t id = fork();
        if (id == 0)
        {
            while (1)
            {
                printf("我是子进程,pid:%d,我的父进程pid:%d\n", getpid(), getppid());
                sleep(1);
            }
        }
        else
        {
            while (1)
            {
              printf("我是父进程,pid:%d,我的父进程pid:%d\n", getpid(), getppid());
              sleep(1);
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ./mytest
    我是父进程,pid:9668,我的父进程pid:2170
    我是子进程,pid:9669,我的父进程pid:9668
    
    • 1
    • 2
    • 3
    • fork 之后,父进程和子进程会共享代码,一般都会执行后续的代码。
    • fork 之后,父进程和子进程返回值不同,给父进程的返回值是子进程的pid,子进程的返回值是0可以通过判断不同的返回值让父子进程执行不同的代码块。

    进程状态

    概念

    运行状态:进程只要在运行队列中就处于运行状态,代表已经准备好随时被调度。

    终止状态:进程还在,只不过永远不运行了,随时等待被释放。

    因为释放也占用资源,所以终止状态存在的意义就是,在操作系统较忙时可以先安排其他更重要的工作,稍后对终止状态的进程进行释放

    阻塞状态

    • 进程不仅需要向 CPU 申请资源,也可能会向磁盘、网卡、显卡等申请资源。如果向CPU申请资源暂时无法满足,则会在运行队列中排队。如果向其他设备申请资源,也是需要排队的。

    • 当进程需要访问某些资源(磁盘网卡等)时,该资源如果暂时没有准备好,或者正在给其他进程提供服务,此时要将当前进程从运行队列中移除放到相应设备的等待队列。这样 CPU 就可以继续运行后面的进程,提高效率。(底层其实就是 PCB 的移动)

    在这个等待过程中,该进程的代码不会被执行,看上去就和卡住了一样,这被称为进程阻塞

    挂起状态

    如果内存不足,而有一些进程短时间内不会被调度(等待的资源短时间内不会就绪),它的代码和数据还存在内存中就是一种浪费,操作系统就会把该进程的代码和数据置换到磁盘上,只留 PCB 在内存中,这样的进程就处于挂起状态。

    Linux 进程状态

    以上是操作系统原理中的概念,具体到 Linux 系统中稍微有一点不一样。

    Linux内核源代码里的定义:

    /*
    * 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 */
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    写一个不停打印 Hello world 的程序:

    #include 
    
    int main()
    {
        while (1)
        {
            printf("Hello world\n");
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行后查看该进程的状态:

    [CegghnnoR@VM-4-13-centos file]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v 'grep'
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
     2170 26046 26046  2170 pts/0    26046 S+    1001   0:08 ./mytest
    
    • 1
    • 2
    • 3

    STAT一栏显示的就是该进程的状态,为S+,S代表睡眠的意思,其实就是阻塞状态,但是这边明明正在不停地打印Hello world,为什么不是运行状态呢?

    其实该程序要运行的代码就一行printf,CPU的速度是极快的,但是显示器的速度慢,绝大部分时间进程都在等待显示器的资源。

    如果你把printf() 一行去掉,再运行看程序状态:

    #include 
    
    int main()
    {
        while (1)
        {
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    [CegghnnoR@VM-4-13-centos file]$ ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v 'grep'
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
     2170 29435 29435  2170 pts/0    29435 R+    1001   0:11 ./mytest
    
    • 1
    • 2
    • 3

    这个进程不用访问其他外设,只等 CPU 的资源,而且是死循环,状态显示R+,也就是运行状态。

    S状态也叫浅度睡眠,或可中断睡眠,意为可以随时被唤醒,或者手动去终止它。

    D状态也是一种阻塞状态,一般指等待磁盘资源。该状态也叫深度睡眠,或不可中断睡眠,因为磁盘的写入删除都要返回一个成功或失败的反馈信息,在这期间该进程必须等待,如果被杀,会导致错误,所以D状态是对该进程的一种保护,使它不可被杀掉。

    X状态是死亡状态,也就是上面说的终止状态。

    Z状态是僵尸状态,当一个Linux中的进程退出的时候,一般不会直接进入X状态,而是进入Z状态,这是为了维护进程的 PCB 中的退出信息,从而让父进程或者操作系统读取。

    僵尸进程的模拟及其危害

    用fork创建一个子进程,然后子进程正常运行5s后退出,父进程一直死循环。

    #include 
    #include 
    #include 
    
    int main()
    {
        pid_t id = fork();
        if (id == 0)
        {
            int  cnt = 5;
            while (cnt)
            {
                printf("我是子进程,我还剩%ds\n", cnt--);
                sleep(1);
            }
            printf("我是子进程,我已经变僵尸了,等待被检测\n");
            exit(0);
        }
        else
        {
            while (1)
            {
                sleep(1);
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    结果:

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ./mytest
    我是子进程,我还剩5s
    我是子进程,我还剩4s
    我是子进程,我还剩3s
    我是子进程,我还剩2s
    我是子进程,我还剩1s
    我是子进程,我已经变僵尸了,等待被检测
    ^C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    同时在另一个终端中使用指令每隔一秒查看这对父子进程的状态:

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ while :; do ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v 'grep'; sleep 1; echo "###################################"; done
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 Z+    1001   0:00 [mytest] 	#变成僵尸状态
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 Z+    1001   0:00 [mytest] 
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059 29858 29858 26059 pts/1    29858 S+    1001   0:00 ./mytest
    29858 29862 29858 26059 pts/1    29858 Z+    1001   0:00 [mytest] 
    ###################################
    ^C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    可以看到,5s后子进程变成了僵尸进程。

    如果父进程一直不回收僵尸状态的子进程,那么该状态就一直维护着,该进程的相关资源不会被释放,造成内存泄漏!

    孤儿进程

    顾名思义,就是父进程提前退出,子进程还在运行。

    父进程退出有bash进程回收,然后子进程会被1号进程(操作系统)领养。子进程退出会被操作系统回收。

    模拟孤儿进程:

    父进程运行三秒后退出,子进程死循环

    #include                                                                                    
    #include                                                                                   
    #include                                                                                   
                                                                                                         
    int main()                                                                                           
    {                                                                                                    
        pid_t id = fork();                                                                               
        if (id == 0)                                                                                     
        {                                                                                                
            while (1)  
            {  
                printf("我是子进程\n");  
                sleep(1);  
            }                                                                                                
        }                                                   
        else                                       
        {                                          
            int cnt = 3;                           
            while (cnt)                            
            {                                      
                printf("我是父进程,我:%d\n", cnt--);  
                sleep(1);                          
            }                                      
            exit(0);                               
        }                                          
        return 0;                                  
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ while :; do ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v 'grep'; sleep 1; echo "###################################"; done
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059  3847  3847 26059 pts/1     3847 S+    1001   0:00 ./mytest
     3847  3848  3847 26059 pts/1     3847 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059  3847  3847 26059 pts/1     3847 S+    1001   0:00 ./mytest
     3847  3848  3847 26059 pts/1     3847 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059  3847  3847 26059 pts/1     3847 S+    1001   0:00 ./mytest
     3847  3848  3847 26059 pts/1     3847 S+    1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
        1  3848  3847 26059 pts/1    26059 S     1001   0:00 ./mytest
    ###################################
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
        1  3848  3847 26059 pts/1    26059 S     1001   0:00 ./mytest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    👆🏻:3 秒后父进程消失,子进程的 ppid 变成 1,表示被操作系统领养了。

    另外,子进程的状态由 S+ 变为 S,有 + 号的表示前台进程,无 + 号的表示后台进程,前台进程可以使用 ctrl+c 终止,后台进程只能用 kill -9 [pid] 的方式终止。

    暂停状态

    T状态t状态都表示暂停。

    T状态表示常规的暂停,比如 kill -19 [pid] 暂停的进程:

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ps ajx | head -1 && ps ajx | grep mytest | grep -v grep
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059  7716  7716 26059 pts/1     7716 S+    1001   0:04 ./mytest
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ kill -19 7716	#输入暂停命令
    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ps ajx | head -1 && ps ajx | grep mytest | grep -v grep
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059  7716  7716 26059 pts/1    26059 T     1001   0:07 ./mytest	#变为T状态
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    另:使用 kill -18 [pid] 可以让进程继续执行。使用 kill -l 可以查看选项。

    t状态表示进程被调试的时候,遇到断点时所处的状态。

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ps ajx | head -1 && ps ajx | grep mytest | grep -v grep
     PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    26059  9465  9465 26059 pts/1     9465 S+    1001   0:00 gdb mytest
     9465  9602  9602 26059 pts/1     9465 t     1001   0:00 /home/CegghnnoR/code/2022_8_12/mytest
    
    • 1
    • 2
    • 3
    • 4

    总结

    • 运行状态对应R状态
    • 终止状态对应Z状态和X状态
    • 阻塞状态对应S状态或D状态
    • 挂起状态对应S状态或D状态或T/t状态

    这就是操作系统原理和 Linux 具体实现的区别。

    进程优先级

    进程优先级就是各个进程获取某种资源的先后顺序。

    [CegghnnoR@VM-4-13-centos 2022_8_12]$ ps -al
    F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    0 S  1001 14456 26059  6  80   0 -  1833 n_tty_ pts/1    00:00:00 mytest
    0 R  1001 14474  2170  0  80   0 - 38595 -      pts/0    00:00:00 ps
    
    • 1
    • 2
    • 3
    • 4

    Linux 下进程优先级由两部分组成:PRI 和 NI,数字越小,代表优先级越高,数字越大,代表优先级越低。

    默认优先级是80,要更改进程优先级就要更改 NI,而不是更改 PRI。NI 表示进程优先级的修正数据。

    NI的取值范围是-20~19,一共40个级别,PRI = 默认优先级 + NI

    用 top 命令可以更改已存在进程的 NI 值

    • top
    • 进入 top 后按 r --> 输入进程 pid --> 输入 NI 值

    其他概念

    竞争性:系统进程数目众多,而 CPU 资源只有少量,所以进程之间具有竞争性,为了高效完成任务,更合理竞争资源,便有了优先级。

    独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰(不会因为一个进程挂掉或者异常,而导致其他进程出现问题)。

    并行:多个进程在多个 CPU 下同时运行。

    并发:多个进程在一个 CPU 下采用进程切换的方式,在一段时间之内,让多个进程都得以推进。

    一个 CPU 一次只能运行一个进程,其他进程都在运行队列里等待,由于并发的存在,才得以让我们在宏观上看像是多个进程在同时运行。

    进程抢占:对于正在 CPU 上运行的进程,如果此时来了个更高优先级的进程,调度器会直接把低优先级进程从 CPU 上剥离,放上更高优先级的进程。

    我们知道队列是不允许插队的,在这种情况下又想实现优先级该怎么办呢?

    实际上一个CPU有多个运行队列,把相同优先级的进程放在同一个队列中,CPU会先选择优先级高的队列里的进程开始运行。

    进程在运行中产生的各种寄存器数据,叫做上下文数据,当进程被剥离时需要保存上下文数据,当进程恢复的时候,需要将曾经保存的上下文数据恢复到寄存器中。上下文数据保存在 PCB 中。

  • 相关阅读:
    第二十一章·备忘录模式
    Java开发岗位职责【杭州多测师】【杭州多测师_王sir】
    Docker出现容器名称重复如何解决
    代码随想录第四十三天|343. 整数拆分 ● 96.不同的二叉搜索树
    时间序列预测:用电量预测 03 Linear(多元线性回归算法)
    适合Python初学者阅读的Github开源代码
    信创产业现状、分析与预测
    95后阿里P7晒出工资单:狠补了这个,真香....
    《算法竞赛进阶指南》 最大子序和
    基于java的家政服务管理系统
  • 原文地址:https://blog.csdn.net/CegghnnoR/article/details/126333266