MIT6.S081操作系统实验-Lab1_Debug记录

Debug记录


1.1 问题描述:在Lab1中的prime实验中,采用单管道进行数据传输,父进程成功写入值,但是子进程无论父进程在管道写入任何值都读只能读到0

第一份代码如下:

#include "kernel/types.h"
#include "user/user.h"

int main()
{
    int pid, fd[2], status;
    pid = fork();
    pipe(fd);

    if(pid == 0) // 子进程
    {   
        int value;
        close(fd[1]);
        read(fd[0], &value, sizeof(int)); 
        printf("value: %d\n", value);
        exit(0);
    }
    else if(pid > 0) 
    {
        int i = 1;
        write(fd[1], &i, sizeof(int)); 
        wait(&status);
        exit(0);
    }
    else
    {
        printf("fork error!!!\n");
        exit(1);
    } 

}

输出结果:

xv6 kernel is booting

hart 1 starting
hart 2 starting
init: starting sh
$ prime
value: 0

 这个问题卡了我整整4天,我将代码规模缩小到只传入一个int值然后读取,考虑了任何阻塞的可能,但是还是读不到传入的值,正在我心如死灰的时候,我重新写了一遍代码,神奇的是,运行成功了!

第二份代码如下:

#include "kernel/types.h"
#include "user/user.h"

int main()
{
    int pid, fd[2], status;
    pipe(fd);
    pid = fork();

    if(pid == 0) // 子进程
    {   
        int value;
        close(fd[1]);
        read(fd[0], &value, sizeof(int));
        printf("value: %d\n", value);
        exit(0);
    }
    else if(pid > 0) //父进程
    {
        int i = 1;
        write(fd[1], &i, sizeof(int)); 
        wait(&status);
        exit(0);
    }
    else
    {
        printf("fork error!!!\n");
        exit(1);
    } 

}

输出:

xv6 kernel is booting

hart 1 starting
hart 2 starting
init: starting sh
$ prime
prime: 1
$ 

不知道你发现了问题所在了吗~

1.2 是的,问题就出在pipe() 和 fork() 的顺序!这个错误对我来说非常非常隐蔽!

 第一种情况:pid = fork()在前,pipe(fd)在后。

此时子进程和父进程都会创建各自的管道,且由于子进程会继承进程的文件描述符,因此子进程和父进程拥有相同的文件描述,分别都指向向读端和写端,但是它们所指的管道不是同一个管道,所以子进程中读到的是自己管道的读端。因为子进程中写入端已经关闭,写入为空。同时无论父进程中写入什么,子进程读到的始终会是0。(PS:如果注释掉子进程中的close(fd[1]),read()会阻塞,因为写入端还没有写入数据同时写入端没有关闭。)

我们在父子进程中输出文件描述符验证一下

#include "kernel/types.h"
#include "user/user.h"

int main()
{
    int pid, fd[2], status;
    pid = fork();
    pipe(fd);
    if(pid == 0) // 子进程
    {   
        int value;
        close(fd[1]);
        read(fd[0], &value, sizeof(int)); 
        printf("value: %d\n", value);
        printf("child fd[0]: %d, fd[1]: %d\n", fd[0], fd[1]);
        exit(0);
    }
    else if(pid > 0) //父进程
    {
        int i = 1;
        write(fd[1], &i, sizeof(int)); 
        wait(&status);
        printf("parent fd[0]: %d, fd[1]: %d\n", fd[0], fd[1]);
        exit(0);
    }
    else
    {
        printf("fork error!!!\n");
        exit(1);
    } 

}

输出:

hart 2 starting
hart 1 starting
init: starting sh
$ prime
prime: 0
child fd[0]: 3, fd[1]: 4
parent fd[0]: 3, fd[1]: 4
$ 

PS:由于水平有限,无法给出这一现象的根本原因,如果有大佬知道的话,帮忙补充,后续如果我补充了这一块的知识,会补上说明。

第二种情况:pipe(fd)在前,pid = fork()在后。

此时父进程创建管道,父子进程拥有相同的文件描述符,并且指向同一个管道,子进程读取到父进程输入的数据。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值