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...
问题排查与解决
核心原因分析
- 浮点运算触发协处理器异常:OS161基于MIPS架构,内核默认未启用浮点协处理器支持。代码中使用
double类型进行除法运算,会生成MIPS浮点指令,触发“Coprocessor unusable”(协处理器不可用)异常(Exception 11)。 - 无效的初始化值:
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
相关产品推荐
相关产品推荐

