进程

本文介绍了进程调度的五种算法:时间片轮转、先来先服务、优先级调度、多级反馈队列和高响应比优先,并详细讲解了Linux操作系统中的PCB(process control block)——task_struct,包括其内容分类和进程状态,如僵尸进程和孤儿进程的特点及危害。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、进程的调度算法
进程的调度算法大致分为五种:
1、时间片轮转调度算法(RR):给每个进程固定的执行时间,根据进程到达的先后顺序让进程在单位时间片内执行,执行完成后便调度下一个进程执行,时间片轮转调度不考虑进程等待时间和执行时间,属于抢占式调度。优点是兼顾长短作业;缺点是平均等待时间较长,上下文切换较费时。适用于分时系统。

2、先来先服务调度算法(FCFS):根据进程到达的先后顺序执行进程,不考虑等待时间和执行时间,会产生饥饿现象。属于非抢占式调度,优点是公平,实现简单;缺点是不利于短作业。

3、优先级调度算法(HPF):在进程等待队列中选择优先级最高的来执行。

4、多级反馈队列调度算法:将时间片轮转与优先级调度相结合,把进程按优先级分成不同的队列,先按优先级调度,优先级相同的,按时间片轮转。优点是兼顾长短作业,有较好的响应时间,可行性强,适用于各种作业环境。

5、高响应比优先调度算法:根据“响应比=(进程执行时间+进程等待时间)/ 进程执行时间”这个公式得到的响应比来进行调度。高响应比优先算法在等待时间相同的情况下,作业执行的时间越短,响应比越高,满足段任务优先,同时响应比会随着等待时间增加而变大,优先级会提高,能够避免饥饿现象。优点是兼顾长短作业,缺点是计算响应比开销大,适用于批处理系统。
二、Linux操作系统下的PCB-task_struct
要了解task_struct,首先要了解PCB。PCB全程process control block,是用来存放进程信息的进程控制块数据结构,它由操作系统进行创建管理,而Linux操作系统下的PCB就是task_struct
task_struct是Linux内核的一种数据结构,他会被装载到RAM里。
task_struct内容分类:

标识符:与进程相关的唯一标识符,用来区别正在执行的进程和其他进程。

状态:描述进程的状态,因为进程有挂起,阻塞,运行等好几个状态,所以都有个标识符来记录进程的执行状态。

优先级:如果有好几个进程正在执行,就涉及到进程被执行的先后顺序的问题,这和进程优先级这个标识符有关。

程序计数器:程序中即将被执行的下一条指令的地址。
内存指针:程序代码和进程相关数据的指针。
- 上下文数据:进程执行时处理器的寄存器中的数据。
I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表等。
记账信息:包括处理器的时间总和,时间限制,记账号等等。
其他信息。

进程状态

TASK_RUNNING(运行状态) 表示进程正在执行或者处于准备执行的状态
TASK_INTERRUPTIBLE (可中断睡眠)进程因为等待某些条件处于阻塞(挂起的状态),一旦等待的条件成立,进程便会从该状态转化成就绪状态
TASK_UNINTERRUPTIBLE(不可中断睡眠) 意思与TASK_INTERRUPTIBLE类似,但是我们传递任意信号等不能唤醒他们,只有它所等待的资源可用的时候,他才会被唤醒。
TASK_STOPPED(停止状态) 进程被停止执行 TASK_TRACED 进程被debugger等进程所监视。
EXIT_ZOMBIE (僵尸进程)进程的执行被终止,但是其父进程还没有使用wait()等系统调用来获知它的终止信息,此时进程成为僵尸进程
EXIT_DEAD (死亡状态)进程被杀死,即进程的最终状态。 TASK_KILLABLE 当进程处于这种可以终止的新睡眠状态中,它的运行原理类似于

进程状态中重点需要了解的是僵尸进程与孤儿进程
僵尸进程
- 当进程退出并且父进程没有读取到子进程退出的退出码时就会产生僵尸进程。
- 僵尸进程会终止状态保持在进程表中,并且一直在等待父进程读取转台代码。
- 僵尸进程的条件:子进程退出,父进程还在运行,但父进程没有读取子进程的状态。
例:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
int main()
{
        pid_t pid;
        pid =fork();
        if (pid == 0)
        {
                printf("this is child process\n");
                exit(0);
        }
        printf("this is father process.");
        sleep(2);
        system("ps -o pid,ppid,state,tty,command");
        printf("father!\n");
        return 0;
}

运行结果如下:
这里写图片描述
从图中可以看到这里有一个进程它的状态是Z。任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。

僵尸进程的危害

僵尸状态一直不退出,PCB一直都要维护。
父进程创建多个子进程不回收,造成内存资源泄露。

孤儿进程

父进程如果提前退出,那么子进程后退出,进入Z
父进程先退出,子进程就是“孤儿进程”
孤儿进程被1号init进程领养,当然要有init进程回收。
例:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
        pid_t id =fork();
        if (id == 0)
        {
                while(1)
                {
                printf("this is child process\n,pid:%d,ppid:%d\n",getpid(),getppid());
                sleep(1);
                }
        }
        else if(id >0)
        {

                printf("this is child process\n,pid:%d,ppid:%d\n",getpid(),getppid());
                sleep(5);
                exit(1);
        }else
        {
                perror("fork");
        }
        return 0;
}

打开另外一个终端对进程进行监测
这里写图片描述

从图中可以看见父进程3804退出后,只有子进程3805成为孤儿进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值