xv6中父子进程输出为何交织?已用wait仍异常,求修复方案
xv6进程输出交织与trap错误的修复方案
你的xv6程序中,fork+wait的逻辑看似能保证父、子进程输出顺序,但实际出现了输出交织和页错误(trap)问题,以下是问题分析与修复方法:
问题代码
#include"types.h" #include"user.h" #include"param.h" int main(){ int pid; pid=fork(); if(pid > 0){ printf(0,"parent: child=%d\n", pid); pid = wait(); printf(0,"child %d is done\n", pid); } else if(pid == 0){ printf(0,"child: exiting\n"); exit(); } else { printf(0,"fork error\n"); } }
错误输出
$ test cphiarlde:n tex:iti ncg hild=4 child 4 is done pid 3 test: trap 14 err 5 on cpu 0 eip 0xffffffff addr 0xffffffff--kill proc
问题根源
- 文件描述符错误:xv6的
printf第一个参数是文件描述符,0代表标准输入(stdin),输出操作应使用1(标准输出stdout)或2(标准错误stderr)。往stdin写入会触发非法内存操作,直接导致页错误(trap 14),同时引发输出混乱。 - printf非原子性(次要):xv6用户态
printf会拆分字符串逐个字符调用write,多进程并发时调度器可能中途切换进程,导致输出交织,但你的核心问题是fd错误引发的异常。
修复方案
1. 修正文件描述符(核心修复)
将所有printf(0, ...)替换为printf(1, ...),指定往标准输出写入。修复后代码:
#include"types.h" #include"user.h" #include"param.h" int main(){ int pid; pid=fork(); if(pid > 0){ printf(1,"parent: child=%d\n", pid); pid = wait(); printf(1,"child %d is done\n", pid); } else if(pid == 0){ printf(1,"child: exiting\n"); exit(); } else { printf(1,"fork error\n"); } }
2. 原子输出优化(可选)
如果要彻底避免多进程输出交织,可使用write系统调用直接写入完整字符串——write对console设备的写入是原子操作,不会被调度器打断:
#include"types.h" #include"user.h" #include"param.h" #include"stdarg.h" // 简易字符串格式化函数 void format_str(char *buf, int size, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsnprintf(buf, size, fmt, ap); va_end(ap); } int main(){ int pid; char buf[64]; pid=fork(); if(pid > 0){ format_str(buf, sizeof(buf), "parent: child=%d\n", pid); write(1, buf, strlen(buf)); pid = wait(); format_str(buf, sizeof(buf), "child %d is done\n", pid); write(1, buf, strlen(buf)); } else if(pid == 0){ write(1, "child: exiting\n", 15); exit(); } else { write(1, "fork error\n", 11); } }
修复后效果
修正fd后,程序会按照预期顺序输出:父进程先打印子进程ID,等待子进程退出后打印完成信息,无输出交织和trap错误。
内容的提问来源于stack exchange,提问作者Shepard Merose
相关产品推荐
相关产品推荐

