打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
利用C语言模拟程序调度机制

素材来源:网络素材


具体内容

  1. 采用的调度算法:高优先数调度算法和先来先服务算法
  2. 进程由进程控制块PCB表示,PCB中包括 a)进程名 b)优先数 c)进程到达时间 d)进程结束时间 e)进程状态 f)已占用CPU时间(进程运行一个时间片后加一)
  3. 运行一个时间片后进程优先级降一级
  4. 利用文件操作模拟进程的操作

概念图

实现过程

  1. 导入的库和宏定义
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>                                   
#include <time.h>
#include <fcntl.h>

#define u8   char
#define u32  unsigned int
#define MAXLINE 1024 //工作队列和等待队列长度
#define MAXNUM  100
#define WAIT 0 //进程状态为WAIT
#define RUN  1 //进程状态为RUN
#define FINISH 2 //进程状态为FINISH
#define NEWBUF  1 //此时工作队列为新队列
#define BUF  0 //此时工作队列为默认队列
#define THENULL 0 //表示进程块此时为NULL
#define THETRUE 1 //表示进程块此时有进程

char* VALUE = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\0';

  1. 建立进程块PCB结构体
struct PCB{
 FILE*   open_file;
 u8 *  file_name;
 clock_t  arrive_time; //到达时间 
 clock_t  level_time; //结束时间
 int  prior_number; //优先级
 u8    program_status; //程序状态
    u8      detection_null_or_value; //判断此时进程块是否为空    
    u8      occupy_time_slice_times; //已占用的CPU时间   
    int     data_write_number;       //记录已经向文件中写入内容的长度  
};
#define PCB_T struct PCB*

  1. 建立工作队列结构体
struct program_queue{
 struct PCB pcb_buf[MAXLINE]; //默认队列,一开始将进程块存入这里
 struct PCB pcb_new_buf[MAXLINE];//与默认队列交替管理进程块
 u32 queue_line;     //工作队列的长度
 u8  buf_state;                  //判断此时正在使用的是哪一个队列
};
#define program_queue_t struct program_queue*

  1. 建立CPU时间片结构体
struct cpu_time_slice{
 clock_t start_time;  //时间片开始执行时间
 clock_t end_time;  //时间片结束执行时间
 u32    time_slice_bulk; //每个时间片的时间,单位ms
};
#define cpu_time_slice_t struct cpu_time_slice*

  1. 清空new队列方法
void bzero_queue_new(program_queue_t queue_t)
{
    for(int i = 0 ; i < MAXLINE ; i++)
    {
        queue_t -> pcb_new_buf[i].detection_null_or_value = THENULL;//detection_null_or_value等于THENULL表示这个结构体为空
    }
}
  1. 清空默认队列方法
void bzero_queue(program_queue_t queue_t)
{
    for(int i = 0 ; i < MAXLINE ; i++)
    {
        queue_t -> pcb_buf[i].detection_null_or_value = THENULL;
    }
}
  1. 初始化时间片机构体方法
void init_time_slice(cpu_time_slice_t time_slice)
{
 time_slice -> time_slice_bulk = 20;//设置一个时间片时间为20ms
    
}
  1. 初始化工作队列方法
void init_program_queue(program_queue_t queue)
{
 bzero_queue(queue);
 bzero_queue_new(queue);
 queue -> queue_line = 0;
 queue -> buf_state = BUF;//设置此时工作队列默认使用的pcb_buf
}
  1. 工作队列排序方法(按照进程优先级排序)
void queue_sort(program_queue_t queue_t)
{
    int len = queue_t -> queue_line;//获取工作队列长度
    if(len == 0)
        return;
    if(queue_t -> buf_state == BUF)//判断当前使用哪个数组作为工作队列
    {
        bzero_queue_new(queue_t);
        struct PCB tm;
  tm.program_status = -1;
        PCB_T tmp_pcb = &tm;
        for(int i = 0 ; i < queue_t -> queue_line ; i++)//开始排序
        {            
            for(int j = 0; j < queue_t -> queue_line ; ++j)
            {
                if(queue_t -> pcb_buf[j].detection_null_or_value == THENULL)
                    continue;                    
                if(j <= 0)
                    tmp_pcb = &(queue_t -> pcb_buf[j]);
                else if(-1 == tmp_pcb -> program_status)
                    tmp_pcb = &(queue_t -> pcb_buf[j]);
                else
                {
                    if(tmp_pcb -> prior_number > queue_t -> pcb_buf[j].prior_number)
                    {
                        tmp_pcb = &(queue_t -> pcb_buf[j]);
                    }
                }
            }
            queue_t -> pcb_new_buf[i] = *tmp_pcb;
            tmp_pcb -> detection_null_or_value = THENULL;
        }
        queue_t -> buf_state = NEWBUF;//由另一个数组接收排序结果,排序完全结束后切换列表目前使用的数组
    }
    else
    {
        bzero_queue(queue_t);
        struct PCB tm;
  tm.program_status = -1;
        PCB_T tmp_pcb = &tm;
        for(int i = 0 ; i < queue_t -> queue_line ; i++)
        {            
            for(int j = 0; j < queue_t -> queue_line ; ++j)
            {
                if(queue_t -> pcb_new_buf[j].detection_null_or_value == THENULL)
                    continue;                    
                if(j <= 0)
                    tmp_pcb = &(queue_t -> pcb_new_buf[j]);
                else if(-1 == tmp_pcb -> program_status)
                    tmp_pcb = &(queue_t -> pcb_new_buf[j]);
                else
                {
                    if(tmp_pcb -> prior_number > queue_t -> pcb_new_buf[j].prior_number)
                    {
                        tmp_pcb = &(queue_t -> pcb_new_buf[j]);
                    }
                }
            }
            queue_t -> pcb_buf[i] = *tmp_pcb;
            tmp_pcb -> detection_null_or_value = THENULL;
        }
        queue_t -> buf_state = BUF;
    }
}
  1. 初始化进程块PCB
void init_pcb_object(PCB_T pcb_t,char** argv,int i)
{
    pcb_t -> open_file = NULL;
 if(NULL == (pcb_t -> open_file = fopen(argv[i],'a')))
 {
  perror('open file error');
  exit(0);
 }
 pcb_t -> file_name = argv[i];        
 pcb_t -> prior_number = rand() % 8//进程优先级由随机数分配
 pcb_t -> arrive_time = clock();  //获取进程进入时间
 pcb_t -> program_status = WAIT;  //设置进程状态为等待
    pcb_t -> detection_null_or_value = THETRUE; //设置次进程块非空
    pcb_t -> occupy_time_slice_times = 0;//初始化使用CPU时间为0
    pcb_t -> data_write_number = 0;      //文件写入内容长度初始化为0
}
  1. 主函数
int main(int argc,char **argv)
{
 if(argc <= 1)
 {
  perror('parameter <= 1');
  exit(1);
 }    
 
 struct program_queue _queue; //创建工作队列对象
 init_program_queue(&_queue);
 
 struct cpu_time_slice cts;  //创建CPU时间片对象
 init_time_slice(&cts);

    int program_numer = argc - 1//设置目前的进程数为argc - 1,该变量用于通过下标访问进程需要-1
    
 for(int i = 1 ; i < argc ; i++)
 {
        init_pcb_object(&(_queue.pcb_buf[i - 1]),argv,i);
        _queue.queue_line++;
 }//循环初始化进程块

    printf('program queue: ');
    for(int i = 1 ; i < argc ; i++)
    {
        printf('[ %s ] , ',_queue.pcb_buf[i - 1].file_name);
    }//打印进程名称
    printf('\n');

    queue_sort(&_queue);//将进程队列进行排序
    printf('program queue sort end...\n');
    
    while(1)//准备执行进程
    {
        if(0 >= program_numer)
            break;
        for(int i = 0 ; i < _queue.queue_line ; i++)
        {            
            if(_queue.buf_state == BUF)
            {
                if(THENULL == _queue.pcb_buf[i].detection_null_or_value)
                    continue;
                printf('wait queue:');
                for(int k = 0 ; k < _queue.queue_line ; k++)
                {
                    if(THENULL == _queue.pcb_buf[k].detection_null_or_value)
                        continue;//如果该进程块为空就跳过
                    printf('[ %s ]',_queue.pcb_buf[k].file_name);
                }//打印等待执行的进程名称
                printf('\nprogram start operation...\n');
                printf('operation program name: %s\n',(_queue.pcb_buf[i].file_name));//打印将要执行的进程名称
                _queue.pcb_buf[i].program_status = RUN;//更改进程块状态
            }
            else
            {
                if(THENULL == _queue.pcb_new_buf[i].detection_null_or_value)
                    continue;
                printf('wait queue:');
                for(int k = 0 ; k < _queue.queue_line ; k++)
                {
                    if(THENULL == _queue.pcb_new_buf[k].detection_null_or_value)
                        continue;
                    printf('[ %s ]',_queue.pcb_new_buf[k].file_name);
                }
                printf('\nprogram start operation...\n');
                printf('operation program name: %s\n',(_queue.pcb_new_buf[i].file_name));
                _queue.pcb_new_buf[i].program_status = RUN;
            }
            
            cts.start_time = clock();//获取开始时间
            while(1)//进程开始执行
            {
                cts.end_time = clock();//获取结束时间
                if(cts.end_time - cts.start_time >= cts.time_slice_bulk)//结束时间 - 开始时间 = 预设的时间片长度则进程终止执行
                {
                    if(_queue.buf_state == BUF)
                    {
                        _queue.pcb_buf[i].program_status = WAIT;
                        _queue.pcb_buf[i].prior_number++;//进程使用CPU时间+1
                        _queue.pcb_buf[i].occupy_time_slice_times++;
                        _queue.pcb_new_buf[i] = _queue.pcb_buf[i];//将进程放到另一个队列等待
                        _queue.pcb_buf[i].detection_null_or_value = THENULL;//将当前队列的此进程块设为空
                    }
                    else
                    {
                        _queue.pcb_new_buf[i].program_status = WAIT;
                        _queue.pcb_new_buf[i].prior_number++;
                        _queue.pcb_new_buf[i].occupy_time_slice_times++;
                        _queue.pcb_buf[i] = _queue.pcb_new_buf[i];
                        _queue.pcb_new_buf[i].detection_null_or_value = THENULL;
                    }
                    
                    break;
                }
                if(_queue.buf_state == BUF)
                {
                    if(VALUE[_queue.pcb_buf[i].data_write_number] == '\0')//判断进程是否已经完成任务
                    {
                        _queue.pcb_buf[i].level_time = clock();//获取结束时间
                        printf('program [ %s ] execute end... program run time: %d ms\n',_queue.pcb_buf[i].file_name,_queue.pcb_buf[i].level_time - _queue.pcb_buf[i].arrive_time);//进程的结束时间减去进程的进入时间计算出进程运行耗时
                        _queue.pcb_buf[i].detection_null_or_value = THENULL;
                        fclose(_queue.pcb_buf[i].open_file);//关闭文件
                        program_numer--;//进程数-1
                        break;
                    }
                    if(-1 == fputc(VALUE[_queue.pcb_new_buf[i].data_write_number],_queue.pcb_new_buf[i].open_file))//向文件中写入数据
                    {
                        perror('write error\n');
                        perror(strerror());
                        for(int i = 0 ; _queue.queue_line ; i++)
                        {
                            fclose(_queue.pcb_buf[i].open_file);
                        }
                        //exit(1);
                    }
                    else
                    {
                        _queue.pcb_buf[i].data_write_number++;//写入内容的长度+1
                    }
                }
                else
                {
                    if(VALUE[_queue.pcb_new_buf[i].data_write_number] == '\0')
                    {
                        _queue.pcb_new_buf[i].level_time = clock();
                        printf('program [ %s ] execute end... program run time: %d ms\n',_queue.pcb_new_buf[i].file_name,_queue.pcb_new_buf[i].level_time - _queue.pcb_new_buf[i].arrive_time);
                        _queue.pcb_new_buf[i].detection_null_or_value = THENULL;
                        fclose(_queue.pcb_new_buf[i].open_file);
                        program_numer--;
                        break;
                    }
                    if(-1 == fputc(VALUE[_queue.pcb_new_buf[i].data_write_number],_queue.pcb_new_buf[i].open_file))
                    {
                        perror('write error\n');
                        perror(strerror());
                        for(int i = 0 ; _queue.queue_line ; i++)
                        {
                            fclose(_queue.pcb_new_buf[i].open_file);
                        }
                        //exit(1);
                    }
                    else
                    {
                        _queue.pcb_new_buf[i].data_write_number++;
                    }
                }
            }
        }
        
        if(_queue.buf_state == BUF)//更换当前队列
        {
            _queue.buf_state = NEWBUF;
            queue_sort(&_queue);//重新按照优先级排序队列
        }
        else
        {
            _queue.buf_state = BUF;
            queue_sort(&_queue);
        }
    }
    
    return 0 ;
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C语言实现时间片轮转法的cpu调度模拟
进程调度
linux设备驱动归纳总结(三):5.阻塞型IO实现
写两个星期OpenCL先(1) | Gary Chan's Blog
信号量以及他们的pv操作
Linux驱动阻塞的实现
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服