You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OS161开发遇Panic错误:Fatal exception 11(协处理器不可用)求助

问题:OS161添加FCFS调度算法后触发内核Panic(协处理器不可用)

在Ubuntu 16系统上为OS161编写First Come First Serve(FCFS)调度算法,将相关代码添加到main.c的kmain函数后,触发内核模式下的Panic错误,具体错误信息为“Fatal exception 11 (Coprocessor unusable)”。

相关代码

FCFS实现代码

#include <types.h>
#include <lib.h>
#include <machine/types.h>
#include <stdlib.h>
#include <FCFS.h> //自定义头文件

void enqueue(Queue *queue, int pid, int arrival_time, int burst_time) {
    Process *new_process = kmalloc(sizeof(Process));
    new_process->pid = pid;
    new_process->arrival_time = arrival_time;
    new_process->burst_time = burst_time;
    new_process->next = NULL;
    if (queue->head == NULL) {
        queue->head = new_process;
        queue->tail = new_process;
    } else {
        queue->tail->next = new_process;
        queue->tail = new_process;
    }
}

int dequeue(Queue *queue) {
    if (queue->head == NULL) {
        return -1;
    }
    int pid = queue->head->pid;
    Process *old_head = queue->head;
    queue->head = queue->head->next;
    if (queue->head == NULL) {
        queue->tail = NULL;
    }
    kfree(old_head);
    return pid;
}

void init_queue(Queue *queue) {
    queue->head = NULL;
    queue->tail = NULL;
}

double calculate_average_wait_time(Process *processes, int num_processes) {
    int current_time = 0;
    int total_wait_time = 0;
    Queue q;
    init_queue(&q);
    for (int i = 0; i < num_processes; i++) {
        int time_difference = processes[i].arrival_time - current_time;
        if (time_difference > 0) {
            current_time += time_difference;
        }
        enqueue(&q, processes[i].pid, processes[i].arrival_time, processes[i].burst_time);
        current_time += processes[i].burst_time;
        total_wait_time += current_time - processes[i].arrival_time - processes[i].burst_time;
    }
    return ((double) total_wait_time) / num_processes;
}

FCFS.h头文件

#ifndef FCFS_H
#define FCFS_H

typedef struct Process {
    int pid;
    int arrival_time;
    int burst_time;
    struct Process *next;
} Process;

typedef struct Queue {
    Process *head;
    Process *tail;
} Queue;

void enqueue(Queue *queue, int pid, int arrival_time, int burst_time);
int dequeue(Queue *queue);
void init_queue(Queue *queue);
double calculate_average_wait_time(Process *processes, int num_processes);

#endif

修改后的main.c的kmain函数

void
kmain(char *arguments)
{
    boot();
    Process process_list[5];
    int num_processes = 0;

    // 填充process_list和num_processes的代码未实现

    // 运行FCFS算法并存储结果
    double average_wait_time = calculate_average_wait_time(process_list, num_processes);

    // 打印平均等待时间或执行其他操作
    kprintf("Average wait time: %f\n", average_wait_time);
    menu(arguments);

    /* 不应执行到此处 */
}

完整错误日志

panic: Fatal exception 11 (Coprocessor unusable) in kernel mode

panic: EPC 0x8000d0cc, exception vaddr 0x0

panic: I can't handle this... I think I'll just die now...

sys161: trace: software-requested debugger stop

sys161: Waiting for debugger connection...


问题排查与解决

核心原因分析

  1. 浮点运算触发协处理器异常:OS161基于MIPS架构,内核默认未启用浮点协处理器支持。代码中使用double类型进行除法运算,会生成MIPS浮点指令,触发“Coprocessor unusable”(协处理器不可用)异常(Exception 11)。
  2. 无效的初始化值:num_processes被设为0,导致calculate_average_wait_time中循环不执行,且会出现0.0/0的无意义运算,虽然这不是直接触发异常的原因,但会导致计算结果无效。

解决步骤

1. 替换浮点运算为整数运算

内核环境中应避免使用浮点类型,将平均等待时间计算改为整数运算:

  • 修改calculate_average_wait_time函数的返回值和实现:
    // FCFS.c中修改函数
    int calculate_average_wait_time(Process *processes, int num_processes) {
        if (num_processes == 0) return 0;
        int current_time = 0;
        int total_wait_time = 0;
        Queue q;
        init_queue(&q);
        for (int i = 0; i < num_processes; i++) {
            int time_difference = processes[i].arrival_time - current_time;
            if (time_difference > 0) {
                current_time += time_difference;
            }
            enqueue(&q, processes[i].pid, processes[i].arrival_time, processes[i].burst_time);
            current_time += processes[i].burst_time;
            total_wait_time += current_time - processes[i].arrival_time - processes[i].burst_time;
        }
        return total_wait_time / num_processes; // 整数除法,若需小数可乘1000后返回
    }
    
  • 更新FCFS.h中的函数声明:
    int calculate_average_wait_time(Process *processes, int num_processes);
    
  • 修改main.c中的调用和打印:
    int average_wait_time = calculate_average_wait_time(process_list, num_processes);
    kprintf("Average wait time: %d\n", average_wait_time);
    
    若需要保留小数精度,可改为return total_wait_time * 1000 / num_processes;,打印时用kprintf("Average wait time: %d.%03d\n", average_wait_time/1000, average_wait_time%1000);。

2. 填充有效的测试数据

修复num_processes为0的问题,添加测试用的进程数据:

Process process_list[5] = {
    {1, 0, 5},
    {2, 1, 3},
    {3, 2, 8},
    {4, 3, 6},
    {5, 4, 2}
};
int num_processes = 5;

3. 确保编译选项禁用浮点支持

检查OS161的Makefile配置,确保没有添加-mfpu等浮点相关编译标志,保持内核默认的无浮点支持配置。


内容的提问来源于stack exchange,提问作者Hassan Hassan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 22:35:02