操作系统实验报告之Linux系统下进程的创建与调度

实验一 Linux系统中进程的创建与调度算法模拟实验

一、实验目的和要求

1.加深对进程概念的理解,进一步认识并发执行的实质。
2.掌握Linux 操作系统中进程的创建和终止操作。
3.掌握在Linux 操作系统中创建子进程并加载新映像的操作。
4.加深对进程概念的理解,明确进程和程序的区别。
5. 深入理解系统如何组织进程。
6. 理解常用进程调度算法的具体实现。

三、进程创建实验:实验内容

 编写一个C 程序,并使用系统调用fork()创建一个子进程。要求如下:

1、 在子进程中分别输出当前进程为子进程的提示、当前进程的PID 和父进程的PID 、根据用户输入确定当前进程的返回值、退出提示等信息;

2、在父进程中分别输出当前进程为父进程的提示、当前进程的PID 和子进程的PID 、等待子进程退出后获得的返回值、退出提示等信息。

 编写另一个C 程序,使用系统调用fork()以创建一个子进程,并使用这个子进程调用exec 函数族以执行系统命令ls 。

四、进程创建实验:实验步骤

(1)在根目录下用vi命令创建一个test1_1.c文件 进行程序编辑
(2)输入gcc test1_1.c -o test1_1,将test1_1.c文件编译输出成test1_1文件
(4)运行可执行文件并输出程序运行结果
输入ls,发现目录下多了一个test1_1文件
再输入./ test1_1,即可运行该文件,并得到输出结果
(5)用vi命令创建test1_2.c文件,并编辑
(6)gcc编译test1_2.c为test1_2,并输入./ test1_2运行文件,得到结果

五、进程创建实验:代码及注释

实验一第一问

#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
#include<stdio.h>

int main(){

        pid_t haizi; /*存储子进程的pid*/
        int retval;    /*用户提供的子进程返回值*/
        int status;    /*父进程的子进程退出状态*/

        /*创建新的进程*/
        haizi = fork();
        if (haizi >= 0) 
        {
                if (haizi == 0) 
                {
                        printf("haizi:I am the haizi process\n");
                        printf("haizi:My PID is %d\n",getpid());  /*输出当前进程的pid*/
                        printf("haizi:My fuqin's PID is %d\n",getppid());  /*输出当前父进程的pid*/
                        printf("haizi:The value of fork return is %d\n",haizi);
                        printf("haizi:Sleep for one second...\n");
                        sleep(1); //让当前进程睡眠1s
                        printf("haizi:Enter an exit value (0~255): ");
                        scanf("%d",&retval);
                        printf("haizi:Goodbye! \n");
                        exit(retval);             /*子进程退出,退出值为用户提供的返回值*/
               }
                else 
               {
                        printf("fuqin:I am the fuqin process!\n");
                        printf("fuqin:My PID is %d\n",getpid());
                        printf("fuqin:The value of my haizi's PID is %d\n", haizi);
                        printf("fuqin:I will now wait for my haizi to exit.\n");
                        wait(&status);
                        printf("fuqin:haizi's exit code is %d\n",WEXITSTATUS(status));/*输出子进程的返回值*/
                        printf("fuqin:Goodbye!\n");
                        exit(0); /*父进程退出*/

                }

        }
        else 
        {
                perror("fork error !\n"); /*显示错误信息*/
                exit(0);
        }

        return 0;
}

实验一第二问

#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>

int main() {

        int rtn;                     /*子进程的返回值*/
        if (fork() == 0) {
                /*The son process execution this process */
                execlp("/bin/ls","ls -al",(char *)0);

                exit(21);   /*显示打印失败信息*/
        }
        else {
                /*父进程等待子进程结束并打印子进程返回值*/
                wait(&rtn);
                printf("child process return %d\n", rtn);
        }
        return 0;
}

六、进程创建实验:实验结果

实验一第一问
首先在主程序中通过 forkO 创建子进程,并根据fork()的返回值确定所处的进程是子进程还是父进程,然后分别在子进 程和当前进程(父进程)中调用 getpidO getppid()、 wait()等函数
在这里插入图片描述图1.1 进程创建的运行结果

实验一第二问
在这里插入图片描述图1.2 进程调用 exec 函数族以执行系统命令 ls

七、进程调度实验:实验内容

 编写C 程序,模拟实现单处理器系统中的进程调度算法,实现对多个进程的模拟调度,要求采用常见的进程调度算法(如先来先服务、时间片轮转和优先级等调度算法)进行模拟调度。

八、进程调度实验:实验步骤

开始运行程序后,出现三个算法选择:1.优先级调度算法;2.先来先服务算法;3.时间轮转算法,选择其中任意一个算法之后,提示输入进程的个数,进程的名称,进程的优先级,进程的运行时间

每个进程的状态可以是就绪W(Wait)、运行R(Run)、或阻塞B(Block)三种状态之一。 每进行一次调度程序都打印一次运行进程、就绪队列、阻塞队列以及各个进程的PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。

输入完成后开始调度
1) 优先级调度算法
每个进程的状态可以是就绪W(Wait)、运行R(Run)、或阻塞B(Block)三种状态之一。 每进行一次调度程序都打印一次运行进程、就绪队列、阻塞队列以及各个进程的PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。进程的相关参数即运行时间、I/O需求等自行设定。
实现动态优先级调度算法:可指定进程的初始优先级(优先级与优先数成反比,优先级最高为0),优先级改变遵循下列原则:进程在就绪队列中每停留一个时间片,优先级加1,进程每运行一个时间片,优先级减3。(说明:本算法在优先级相同的情况下,选择到达时间早的进程进行运行)

2) 先来先服务算法
每个进程的状态可以是就绪W(Wait)、运行R(Run)、或阻塞B(Block)三种状态之一。 每进行一次调度程序都打印一次运行进程、就绪队列、阻塞队列以及各个进程的PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。进程的相关参数即运行时间、I/O需求等自行设定。

3) 时间片轮转算法
进程调度程序总是选择就绪队列中第一个进程,允许其占有处理机一个时间片的时间。当执行的时间片用完时,调度程序便停止该进程的执行,并将它送就绪队列的末尾,等待分配下一时间片再执行。然后把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程,在一给定的时间内,均能获得一时间片处理机执行时间。

九、进程调度实验:代码及注释改进后的代码:

#include <stdio.h>
#include <stdlib.h>
// 定义进程控制块PCB
struct pcb {
    char name[10];
    char state;//进程状态
    int super;//优先级
    int ntime;//需要时间
    int rtime;//已经执行时间
    struct pcb* link;
}*ready = 0, * p;
typedef struct pcb PCB;
int runningTime = 0;
//求进程数
int PCB_Len() {
    int pcb_len = 0;
    PCB* pr = ready;
    while (pr != 0) {
        pcb_len++;
        pr = pr->link;
    }
    return pcb_len;
}
//建立对进程进行最高优先级调度算法,同级条件下进行先来先服务算法函数
void sort() {
    PCB* temp;
    p->super -= 1;
    temp = ready;
    if (temp != 0) {
        if (p->super > temp->super) {//插入队首
            p->link = ready;
            ready = p;
        }
        else {
            while (temp != 0) {
                if (temp->link == 0) {//插入队尾
                    temp->link = p;
                    break;
                }
                if (p->super > temp->link->super) {
                    p->link = temp->link;
                    temp->link = p;
                    break;
                }
                temp = temp->link;
            }
        }
    }
    else {
        ready = p;
    }
}
//连接pcb
void linkpcb() {
    PCB* first;
    if (ready == 0) {//插入队首
        p->link = ready;
        ready = p;
    }
    else {//按从大到小插入到合适位置
        first = ready;
        if (p->super > first->super) { //插入到队首
            p->link = first;
            ready = p;
        }
        else {
            while (first->link != 0 && p->super <= first->link->super) {
                first = first->link;
            }
            if (first->link != 0) {
                p->link = first->link;
                first->link = p;
            }
            else {
                first->link = p;
                p->link = 0;
            }
        }
    }
}
// 建立进程控制块输入函数
void input() {
    int i, num;
    printf("请输入即将运行的进程总数目:");
    scanf("%d", &num);
    for (i = 0; i < num; i++) {
        p = (PCB*)malloc(sizeof(PCB));//申请空间,指针
        if (p == 0) {
            printf("内存分配不成功!\n");
        }
        else {
            printf("\n请输入第%d个进程名称:", i + 1);
            scanf("%s", p->name);
            printf("请输入第%d个进程的优先级:", i + 1);
            scanf("%d", &p->super);
            printf("请输入第%d个进程运行时间:", i + 1);
            scanf("%d", &p->ntime);
            p->rtime = 0;
            p->state = 'W';
            p->link = 0;
            linkpcb();
        }
    }
}
//建立进程显示函数,用于显示当前进程
void disp(PCB* pr) {
    printf("Name\tState\tSuper\tNTime\tRunTime\n");
    printf("%s\t", pr->name);
    printf("%c\t", pr->state);
    printf("%d\t", pr->super);
    printf("%d\t", pr->ntime);
    printf("%d\t\n", pr->rtime);
}
//建立函数查看进程
void check() {
    PCB* temp;
    printf("\n **** 当前正在运行的进程是:%s\n", p->name); //显示当前运行进程
    disp(p);
    temp = ready;
    printf("\n ****当前就绪队列状态为:\n"); //显示就绪队列状态
    if (temp == 0)printf("\n 就绪队列为空。\n ");
    while (temp != 0) {
        disp(temp);
        temp = temp->link;
    }
    free(temp);
}
//建立进程就绪函数(进程运行时间到,置运行状态)
void running() {
    if (p->rtime == p->ntime) {//进程已完成
        printf("\n 进程 [%s] 已完成.\n", p->name);
    }
    else {
        sort(); //调用sort函数
    }
}
//先来先服务和时间片轮转算法的连接pcb
void linkpcb_r() {
    PCB* first;
    if (ready == 0) {//插入队首
        p->link = ready;
        ready = p;
    }
    else {//按先后顺序插入到合适位置
        first = ready;
        while (first->link != 0 ) {
            first = first->link;
        }
        first->link = p;
        p->link = 0;
    }
}
//先来先服务算法的输入
void input_f() {
    int i, num;
    printf("请输入即将运行的进程总数目:");
    scanf("%d", &num);
    for (i = 0; i < num; i++) {
        p = (PCB*)malloc(sizeof(PCB));//申请空间,指针
        if (p == 0) {
            printf("内存分配不成功!\n");
        }
        else {
            printf("\n请输入第%d个进程名称:", i + 1);
            scanf("%s", p->name);
            printf("请输入第%d个进程的优先级:", i + 1);
            scanf("%d", &p->super);
            printf("请输入第%d个进程运行时间:", i + 1);
            scanf("%d", &p->ntime);
            p->rtime = 0;
            p->state = 'W';
            p->link = 0;
            linkpcb_r();
        }
    }
}
//先进先出算法的查看进程
void check_f(PCB* temp) {
    printf("\n **** 当前正在运行的进程是:%s\n", temp->name); //显示当前运行进程
    disp(temp);
    printf("\n ****当前就绪队列状态为:\n"); //显示就绪队列状态
    if (temp->link == 0)printf("\n 就绪队列为空。\n ");
    while (temp->link != 0) {
        disp(temp->link);
        temp = temp->link;
    }
}
//建立先来先服务算法函数
int running_f(int n) {
    PCB* temp;
    temp = ready;
    while (temp!= 0 &&temp->rtime<temp->ntime) {
        printf("\n\nThe execute number:%d\n", ++n);
        temp->state = 'R';
        check_f(temp);
        temp->rtime += 1;//运行时间加1;
        if (temp->rtime == temp->ntime) {//进程已完成
            printf("\n 进程 [%s] 已完成.\n", temp->name);
        }
    }
    return n;
}
//时间片轮转算法查看进程
void check_r(PCB* temp,PCB* temp1) {
    int flag=0;
    printf("\n **** 当前正在运行的进程是:%s\n", temp->name); //显示当前运行进程
    disp(temp);
    printf("\n ****当前就绪队列状态为:\n"); //显示就绪队列状态
    while (temp1 != 0 ) {
        if(temp1->ntime!=temp1->rtime && temp1!=temp)
        {
            disp(temp1);
            flag=1;
        }
        temp1 = temp1->link;
    }
    if (flag == 0)printf("\n 就绪队列为空。\n ");
}
//建立时间片轮转算法函数
int running_r(int n) {
    PCB* temp;
    PCB* temp1;
    temp = ready;
    temp1=ready;
    while (temp!=0) {
        if(temp->rtime<temp->ntime)
        {
            printf("\n\nThe execute number:%d\n", ++n);
            temp->state = 'R';
            check_r(temp,temp1);
            temp->rtime += 1;//运行时间加1
        }
       if(temp->rtime == temp->ntime)
        {//进程已完成
            printf("\n 进程 [%s] 已完成.\n", temp->name);
        }
        temp=temp->link;
        
    }
    
    return n;
}
//时间片轮转算法输入
int input_r() {
    int i, num,k=0;
    printf("请输入即将运行的进程总数目:");
    scanf("%d", &num);
    for (i = 0; i < num; i++) {
        p = (PCB*)malloc(sizeof(PCB));//申请空间,指针
        if (p == 0) {
            printf("内存分配不成功!\n");
        }
        else {
            printf("\n请输入第%d个进程名称:", i + 1);
            scanf("%s", p->name);
            printf("请输入第%d个进程的优先级:", i + 1);
            scanf("%d", &p->super);
            printf("请输入第%d个进程运行时间:", i + 1);
            scanf("%d", &p->ntime);
            p->rtime = 0;
            p->state = 'W';
            p->link = 0;
            linkpcb_r();
            if(p->ntime>k)
            {
                k=p->ntime;
            }
        }
    }
    return k;
}
int main() {
    int len, h = 0;
    int k,a=0;
    printf("***请选则调度算法***\n");
    printf("1.优先度调度算法\n");
    printf("2.先进先出调度算法\n");
    printf("3.时间片轮转调度算法\n");
    scanf("%d",&a);
    switch (a) {
        case 1:
            input();//输入进程
            len = PCB_Len();
            while ((len != 0) && (ready != 0)) {
                printf("\n\nThe execute number:%d\n", ++h);
                p = ready;
                ready = p->link;
                p->link = 0;
                p->state = 'R';
                check();//查看进程
                p->rtime += 1;//运行时间加1;
                p->state = 'W';//置为就绪状态
                running();
            }
            break;
        case 2:
            input_f();//输入进程
            len = PCB_Len();
            while ((len != 0) && (ready != 0)) {
                h=running_f(h) ;
                p = ready;
                ready = p->link;
            }
        case 3:
            k=input_r();//输入进程
            for(int i=0;i<k;i++){
                h=running_r(h);
            }
            
        default:
            break;
    }
   
    printf("\n\n 进程已经完成.\n");
    return 0;
}

十、进程调度实验:实验结果

在这里插入图片描述图1.3优先级调度程序的运行结果1
在这里插入图片描述图1.4优先级调度程序的运行结果2
在这里插入图片描述图1.5优先级调度程序的运行结果3
在这里插入图片描述图1.6优先级调度程序的运行结果4
改进后的代码(优先级+FIFO+RR)

在这里插入图片描述图1.7优先级调度程序的运行结果

在这里插入图片描述图1.8FIFO调度程序的运行结果
在这里插入图片描述
图1.9RR调度程序的运行结果

十一、实验思考

1、 总结调用fork()函数后的三种返回情况。
当fork函数返回值为 小于0,表示没有成功创建子进程。原来的进程仍在执行
当fork函数返回值为 0,表示子进程创建成功,且当前进程为 子进程
当fork函数返回值为 大于0,表示返回值为父进程的返回

2、 总结fork()和wait()配合使用的清况,并尝试在父进程中取消wait()函数,观察进程的运行情况。
进程一旦调用了wait(),就立即阻塞自己,由wait()自动分析是否当前进程的某个子
进程已经退出,如果让它找到了这样一个已经变成僵尸态的子进程,wait ()就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait ()就会一直阻塞在这里,直到有一个出现为止。wait()要与fork()配套出现,如果在使用fork()之前调用wait(),wait()的返回值则为-1,正常情况下wait()的返回值为子进程的PID

3、 验证、总结exec 函数族的具体使用方法。

六个函数的用法和相应参数
int execl(const char *path, const char *arg, …)
int execv(const char *path, char *const argv[])
int execle(const char *path, const char *arg, …, char *const envp[])
int execve(const char *path, char *const argv[], char *const envp[])
int execlp(const char *file, const char *arg, …)
int execvp(const char *file, char *const argv[])

  1. 在你实现的进程调度程序中,调度模式是抢占式还是非抢占式?

  2. 若调度算法中,每运行一次就将优先数减2, 同时将运行时间加1,其他条件不变,则在程序中如何修改?

将每一次rtime运行时间由+1变为+2,将每一次super优先度r-1变为-2,增加判断进程是否会在时间片结束前完成,若会,则直接进入下一个时间片。

  1. 如何将调度算法改为固定优先数调度算法?

在动态优先数上进行改变即可,只需要排一次序,不需要后面优先级改变后的排序,在运行时不改变进程的优先级

  1. 如何基于上述调度算法来实现先来先服务和时间片轮转调度算法?

具体实现如上代码所示,
在main主函数中编写switch case语句,让用户选择使用何种算法,先来先服务算法与时间片轮转调度算法相比优先度调度算法,在pcb连接时不需要重新排序,按进入顺序即可,在查看进程时,先来先服务与优先度调度算法大致相同,可由当前进程开始顺序向后查找,时间片轮转调度算法则需考虑其他所有进程的状态。先来先服务调度算法的实现为从前到后依次执行完所有进程,时间片轮转调度算法的实现则为每个进程运行一个时间片的时间,直到完成该进程。

操作系统 进程创建实验报告 调用fork( )创建进程 实验原理: 一) 进程 UNIX中,进程既是一个独立拥有资源的基本单位,又是一个独立调度的基本单位。一个进程实体由若干个区(段)组成,包括程序区、数据区、栈区、共享存储区等。每个区又分为若干页,每个进程配置有唯一的进程控制块PCB,用于控制和管理进程。 PCB的数据结构如下: 1、进程表项(Process Table Entry)。包括一些最常用的核心数据: 进程标识符PID、用户标识符UID、进程状态、事件描述符、进程和U区在内存或外存的地址、软中断信号、计时域、进程的大小、偏置值nice、指向就绪队列中下一个PCB的指针P_Link、指向U区进程正文、数据及栈在内存区域的指针。 2、U区(U Area)。用于存放进程表项的一些扩充信息。 每一个进程都有一个私用的U区,其中含有:进程表项指针、真正用户标识符u-ruid(read user ID)、有效用户标识符u-euid(effective user ID)、用户文件描述符表、计时器、内部I/O参数、限制字段、差错字段、返回值、信号处理数组。 由于UNIX系统采用段页式存储管理,为了把段的起始虚地址变换为段在系统中的物理地址,便于实现区的共享,所以还有: 3、系统区表项。以存放各个段在物理存储器中的位置等信息。 系统把一个进程的虚地址空间划分为若干个连续的逻辑区,有正文区、数据区、栈区等。这些区是可被共享和保护的独立实体,多个进程可共享一个区。为了对区进行管理,核心中设置一个系统区表,各表项中记录了以下有关描述活动区的信息: 区的类型和大小、区的状态、区在物理存储器中的位置、引用计数、指向文件索引结点的指针。 4、进程区表 系统为每个进程配置了一张进程区表。表中,每一项记录一个区的起始虚地址及指向系统区表中对应的区表项。核心通过查找进程区表和系统区表,便可将区的逻辑地址变换为物理地址。 二) 进程映像 UNIX系统中,进程进程映像的执行过程,也就是正在执行的进程实体。它由三部分组成: 1、用户级上、下文。主要成分是用户程序; 2、寄存器上、下文。由CPU中的一些寄存器的内容组成,如PC,PSW,SP及通用寄存器等; 3、系统级上、下文。包括OS为管理进程所用的信息,有静态和动态之分。 三) 所涉及的系统调用 1、fork( ) 创建一个新进程系统调用格式: pid = fork( ) 参数定义: int fork( ) fork( )返回值意义如下: 0:在子进程中,pid变量保存的fork( )返回值为0,表示当前进程是子进程。 >0:在父进程中,pid变量保存的fork( )返回值为子进程的id值(进程唯一标识符)。 -1:创建失败。 如果fork( )调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork( )被调用了一次,但返回了两次。此时OS在内存中建立一个新进程,所建的新进程是调用fork( )父进程(parent process)的副本,称为子进程(child process)。子进程继承了父进程的许多特性,并具有进程完全相同的用户级上下文。父进程进程并发执行。 核心为fork( )完成以下操作: (1)为新进程分配一进程表项和进程标识符 进入fork( )后,核心检查系统是否有足够的资源来建立一个新进程。若资源不足,则fork( )系统调用失败;否则,核心为新进程分配一进程表项和唯一的进程标识符。 (2)检查同时运行的进程数目 超过预先规定的最大数目时,fork( )系统调用失败。 (3)拷贝进程表项中的数据 将父进程的当前目录和所有已打开的数据拷贝到子进程表项中,并置进程的状态为“创建”状态。 (4)子进程继承父进程的所有文件 对父进程当前目录和所有已打开的文件表项中的引用计数加1。 (5)为子进程创建进程上、下文 进程创建结束,设子进程状态为“内存中就绪”并返回子进程的标识符。 (6)子进程执行 虽然父进程进程程序完全相同,但每个进程都有自己的程序计数器PC(注意子进程的PC开始位置),然后根据pid变量保存的fork( )返回值的不同,执行了不同的分支语句。
(1)进程的软中断通信 #include #include #include #include int wait_flag; void stop(); main( ) { int pid1, pid2; // 定义两个进程号变量 signal(2,stop); // 或者 signal (14,stop); while((pid1 = fork( )) == -1); // 若创建进程1不成功,则空循环 if(pid1 > 0) { // 子进程创建成功,pid1为进程号 while((pid2 = fork( )) == -1); // 创建进程2 if(pid2 > 0) { wait_flag = 1; //sleep(1); // 父进程等待5秒 kill(pid1,SIGUSR1); // 杀死进程1 kill(pid2,SIGUSR2); // 杀死进程2 wait(0); wait(0); printf("\n Parent process is killed !!\n"); exit(0); // 父进程结束 } else { wait_flag = 1; signal(SIGUSR2,stop); // 等待进程2被杀死的中断号17 printf("\n Child process 2 is killed by parent !!\n"); exit(0); } } else { wait_flag = 1; signal(SIGUSR1,stop); // 等待进程1被杀死的中断号16 printf("\n Child process 1 is killed by parent !!\n"); exit(0); } } void stop() { wait_flag = 0; } (2)进程的管道通信 #include #include #include int pid1,pid2; // 定义两个进程变量 main( ) { int fd[2]; char OutPipe[100],InPipe[100]; // 定义两个字符数组 pipe(fd); // 创建管道 while((pid1 = fork( )) == -1); // 如果进程1创建不成功,则空循环 if(pid1 == 0) { lockf(fd[1],1,0); // 锁定管道 sprintf(OutPipe,"\n Child process 1 is sending message!\n"); write(fd[1],OutPipe,50); // 向管道写入数据 sleep(5); // 等待读进程读出数据 lockf(fd[1],0,0); // 解除管道的锁定 exit(0); // 结束进程1 } else { while((pid2 = fork()) == -1); // 若进程2创建不成功,则空循环 if(pid2 == 0) { lockf(fd[1],1,0); sprintf(OutPipe,"\n Child process 2 is sending message!\n"); write(fd[1],OutPipe,50); sleep(5); lockf(fd[1],0,0); exit(0); } else { wait(0); // 等待子进程1 结束 read(fd[0],InPipe,50); // 从管道中读出数据 printf("%s\n",InPipe); // 显示读出的数据 wait(0); // 等待子进程2 结束 read(fd[0],InPipe,50); printf("%s\n",InPipe); exit(0); // 父进程结束 } } }
在C语言中编写一个模拟单机处理系统中的进程调度算法,通常会涉及到以下几个步骤: 1. 定义进程结构体:首先,我们需要创建一个包含进程ID、优先级、状态(如运行、就绪、等待)、CPU时间片等属性的数据结构。 ```c typedef struct { int pid; int priority; enum {RUNNING, SLEEPING, READY} state; float cpu_time; } Process; ``` 2. 创建进程队列:使用链表或其他数据结构存储进程,比如先来先服务(FCFS),短进程优先(SJF)或抢占式优先级调度(Preemptive Priority Scheduling)等。 3. 实现调度算法: - FCFS (First-Come, First-Served): 按照进程到达顺序进行调度,每个进程获得一次CPU时间片。 - SJF (Shortest Job First): 根据进程预计完成时间排序,最小的先执行。 - PP (Priority-Based Scheduling): 根据进程的优先级进行调度,高优先级进程优先获取CPU资源。 4. 调度函数:根据选择的调度算法,实现相应的切换进程逻辑。例如,在抢占式优先级调度中,当有更高优先级的进程就绪时,将当前进程挂起并切换到新进程。 ```c void schedule(Process *processes, int process_count) { // ...根据调度算法选择合适的进程操作... } ``` 5. 用户界面:提供命令行接口让用户输入进程信息(pid、优先级等),并观察调度结果。 6. 主循环:不断读取用户的输入,更新进程状态,并调用调度函数。 ```c while (1) { Process user_input = get_user_input(); update_processes(user_input); schedule(processes, process_count); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@小冯@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值