战点 2024-05-05 16:51 采纳率: 17.4%
浏览 15

能否补全一下阻塞和唤醒代码


#include<stdio.h>
#include<stdlib.h>
#define getpch(type) (type*)malloc(sizeof(type))
#define nothing 0

typedef struct pcb{  //自定义结构体:进程管理块pcb
    char name[10];  //进程名字
    char state;     //进程状态 
    int ntime;      //进程需要运行的时间
    int rtime;      //进程已经运行的时间
    struct pcb *link;  //进程队列链指针 
}PCB;

//初始化就绪队列,进程插入位置的变量,ready首指针,pfend尾指针,p临时变量,stop阻塞队列首指针,stopend阻塞队列尾指针 
PCB  *ready = nothing, *pfend=nothing,*p=nothing,*stop = nothing,*stopend=nothing; 

//使用户仅能输入整数
int geti()  
{
    char ch;
    int i=0;
    fflush(stdin);  //清除输入缓存 ,防止干扰后续的输入操作
    ch=getchar();

    while(ch == '\n'){
        //printf("\tf输入不能为空..请重新输入\n");
        fflush(stdin);
        ch=getchar();
    }
    while(ch!='\n'){  //检验输入是否为合法字符 
        if(ch>'9' || ch<'0'){  
            printf("\t输入有误!!输入只能为正整数,请重新输入…\n");
            fflush(stdin);
            i=0;
            ch=getchar();
        }else{
            i=i*10+(ch-'0');  //字符转换为数字 
            ch=getchar();
        }
    }
    return i;
}

//先来先服务插入进程
void fcfs()
{
    if(!ready){  //就绪队列为空 
        ready=p;
        pfend=p;
    }
    else{        //就绪队列非空,插入队尾 
        p->link=pfend->link;
        pfend->link=p;
        pfend=p;
    }
}

/*建立num个进程控制块函数
  已运行时间=0,状态=w 
*/
void input()
{
    int i,num;
    printf("\n请输入进程的个数?");
    num=geti();
    for(i=0;i<num;i++)
    {
        printf("\n进程号No.%d:\n",i+1);
        p=getpch(PCB);  // 创建进程块p
        printf("\n输入进程名:");
        scanf("%s",p->name);  // 初始化进程名字
        printf("\n输入进程运行时间:");
        p->ntime=geti();
        printf("\n");
        p->rtime=0;
        p->state='w';  // 初始化其状态为就绪状态
        p->link=nothing;
        fcfs();  //按照先来先服务进入就绪队列 
    }
}

/*显示当前系统内进程及进程信息*/
void disp(PCB *pr)
{
    printf("\nname\t state\t ntime\t rtime\t \n");
    printf(" |%s\t",pr->name);
    printf(" |%c\t",pr->state);
    printf(" |%d\t",pr->ntime);
    printf(" |%d\t",pr->rtime);
    printf("\n");
}

 /*建立进程查看函数*/
void check()
{
    PCB *pr;
    if(ready !=nothing){
        printf("\n****当前正在运行的进程是:%s",ready->name);/*显示当前运行的进程*/
        disp(ready);
        pr=ready->link;
        printf("\n****当前就绪队列状态为:\n");/*显示就绪队列状态*/
        while(pr!=nothing)
        {
            disp(pr);
            pr=pr->link;
        }
    }
    printf("\n****当前就阻塞队列的状态为:\n");
    pr=stop;
    while(pr!=nothing){
        disp(pr);
        pr=pr->link;
    }
}

 /*撤销进程,进程运行结束*/
void destroy()
{
    printf("\n进程[%s]已完成.\n",ready->name);
    p=ready;
    ready=ready->link;
    free(p);
}

/*建立进程就绪函数(进程运行时间到,置就绪状态)*/
void running() 
{
    (ready->rtime)++;
    check();
    if(ready->rtime==ready->ntime){
        destroy();
        return;
    }
}

/*阻塞进程*/ 
void block()
{
    if(!stop){//阻塞队列为空 
         ready->state='b';
                  //补全代码
         
    }
    else{//阻塞队列不为空 
        ready->state='b';
        /补全代码

         
    }
    stopend->link=nothing;
}

/*阻塞进程唤醒*/ 
void wake()
{
    if(stop==nothing){
        printf("\n阻塞队列为空,请进行其他操作");
        return;
    }
    else{
        if(ready!=nothing){//就绪队列不为空 
            
            
        }
        else{//就绪队列为空 
            //待补全
             
        }
        //待补全
    }
}

int main()
{
    char ch;
    input();
    while(ready!=nothing || stop!=nothing) //系统中存在进程 
    {
        if(ready!=nothing){
            printf("\nThe execute name:%s\n",ready->name);
            ready->state='R';
            //check();
            running();
            //check();
        }
        else{
            check();
        }
        printf("\n按i键添加新进程…s键阻塞进程…w键唤醒进程\n按其他任意键继续运行…\n");
        fflush(stdin);
        ch=getchar();
        if(ch=='i' || ch=='I')
            input();
        if(ch=='s' || ch=='S')
            block();
        if(ch=='w' || ch=='W')
            wake(); 
}
printf("\n\n进程已经完成\n");
getchar();
return 0;
}
  • 写回答

6条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-05 16:51
    关注

    引自免费微信小程序:皆我百晓生

    在给定的代码中,你需要实现阻塞和唤醒功能。首先,我们来看如何修改block()函数以将进程加入阻塞队列。

    block()函数中,你需要检查阻塞队列是否为空。若为空,则将当前进程添加到阻塞队列的头部。若不为空,将当前进程添加到阻塞队列的尾部。下面是修改后的block()函数:

    void block()
    {
        if (!stop) // 阻塞队列为空
        {
            ready->state = 'b';
            stop = ready;
            stopend = ready;
        }
        else // 阻塞队列不为空
        {
            ready->state = 'b';
            stopend->link = ready;
            stopend = ready;
        }
    }
    

    接下来,我们需要修改wake()函数以从阻塞队列中唤醒一个进程并将其放入就绪队列。当就绪队列为空时,我们将阻塞队列的第一个进程移动到就绪队列的头部。以下是修改后的wake()函数:

    void wake()
    {
        if (stop == nothing)
        {
            printf("\n阻塞队列为空,请进行其他操作");
            return;
        }
        else
        {
            if (ready != nothing) // 就绪队列不为空
            {
                // 暂时保存就绪队列中的第一个进程,用于恢复原样
                PCB *temp = ready;
                running(); // 运行就绪队列中的下一个进程
                ready = temp;
            }
            else // 就绪队列为空
            {
                ready = stop; // 阻塞队列的第一个进程变成就绪队列的第一个进程
                if (ready->link) // 如果阻塞队列还有其他进程
                    stop = ready->link;
                else
                    stop = nothing; // 否则阻塞队列也变为为空
                stopend = nothing;
            }
    
            // 更新阻塞队列的尾部指针
            if (stop != nothing)
                stopend = stop;
        }
    }
    

    现在,代码应该可以正确地处理阻塞和唤醒操作了。请注意,这个实现没有考虑到多进程并发的情况,实际应用中可能需要添加互斥锁等同步机制来保证线程安全。另外,为了简化代码,这里没有处理异常情况,例如尝试唤醒一个已经不存在的阻塞进程。在实际项目中,你应该增加适当的错误检查和处理。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 5月5日

悬赏问题

  • ¥15 CCF-CSP 2023 第三题 解压缩(50%)
  • ¥30 comfyui openpose报错
  • ¥20 Wpf Datarid单元格闪烁效果的实现
  • ¥15 图像分割、图像边缘提取
  • ¥15 sqlserver执行存储过程报错
  • ¥100 nuxt、uniapp、ruoyi-vue 相关发布问题
  • ¥15 浮窗和全屏应用同时存在,全屏应用输入法无法弹出
  • ¥100 matlab2009 32位一直初始化
  • ¥15 Expected type 'str | PathLike[str]…… bytes' instead
  • ¥15 三极管电路求解,已知电阻电压和三级关放大倍数