MIB 6.1810实验Xv6 and Unix utilities(3)pingpong

Mit6.S081-实验1-Xv6 and Unix utilities-pingpong问题_Isana_Yashiro的博客-CSDN博客

Write a user-level program that uses xv6 system calls to ''ping-pong'' a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to the child; the child should print "<pid>: received ping", where <pid> is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print "<pid>: received pong", and exit. Your solution should be in the file user/pingpong.c.

难度:easy

题目:写一个pingpong.c 实现系统调用ping-pong,实现进程之间的管道通信。

管道(pipe)是一种最基本的进程间通信机制。

管道分为 读出端写入端 两个部分,进程可以向写端写入数据,也可以从读端读出数据。通过pipe系统调用,内核会为用户进程创建管道,同时返回两个文件描述符,用以描述管道的读写端,

cpp 复制代码
int p[2];
int ret;
ret = pipe(p); /*正常创建后,p[1]为管道写入端,p[0]为管道读出端*/ 

通过文件描述符,可以向管道中写入和读取数据

cpp 复制代码
int write = write(p[1], buffer, n);
int read = read(p[0], buffer, n);

进程通常只持有某个管道的读出端或者写入端,因此使用的时候需要将另一端关闭。

实现:

cd user

vim pingpong.c

make qemu

pingpong.c

cpp 复制代码
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int main() {
    int p[2];
    int pid;
    pipe(p);
    pid = fork();
    char text[10];
    if (pid == 0) {
        read(p[0],text,10);
        printf("%d: received %s\n", getpid(),text);
        write(p[1],"pong",10);
        exit(0);
    } else { 
        write(p[1],"ping",10);
        wait(0);//父进程阻塞,等待子进程读取
        read(p[0],text,10);
        printf("%d:received %s\n",getpid(),text);

        exit(0);
    }
}

补充:管道的使用示例

cpp 复制代码
int p[2];
pipe(p);
int pid=fork();
if(pid>0){
    close(p[READ]);
    write(p[1],...);
    close(p[WRITE]);
    wait(0);
}else{
    close(p[WRITE]);
    read(p[READ],...);
    close(p[READ]);
    exit(0);
}

p是2个整数的数组

pipe(p)创建一个一个管道,p表示文件标识符的数组,可以进行管道操作。

p[0]用于读取,p[1]用于写入。

fork()函数用来创建一个子进程。如果成功创建,将返回两次,在父进程中返回子进程的PID(大于0),在子进程中返回0。

read如果读不到数据就会进入阻塞状态。所以先执行父进程,在执行子进程。

输出乱序问题

所以如果不对两个字串读出和写入过程进行限制,会导致资源访问的冲突。因此,我们采取调用函数wait()的方式,保证同一时刻管道内只有一个资源的写入和读取。

注意:在linux系统中:父进程的wait()一定和子进程的exit()成对出现配合使用。同时,父进程也需要调用exit(0)

  • exit() :子进程调用 exit() 函数来正常终止自己的执行。exit() 函数将子进程的状态传递给父进程。子进程可以通过传递一个整数状态值来向父进程报告它的终止状态。这个状态值通常代表了子进程的结束状态,比如返回码或错误码。

  • wait() :父进程可以调用 wait() 函数等待子进程的结束。当父进程调用 wait() 时,它会被阻塞,直到它的一个子进程结束。一旦子进程结束,父进程就会收到关于子进程终止状态的信息。父进程可以通过 wait() 获取子进程的终止状态,并且清理子进程的资源。

相关推荐
小王努力学编程22 分钟前
LangChain——AI应用开发框架(核心组件1)
linux·服务器·前端·数据库·c++·人工智能·langchain
EmbedLinX3 小时前
一文理解后端核心概念:同步/异步、阻塞/非阻塞、进程/线程/协程
linux·服务器·c语言·网络
小王努力学编程3 小时前
LangChain——AI应用开发框架(核心组件2)
linux·服务器·c++·人工智能·python·langchain·信号
云服务器租用费用3 小时前
京东云主机企业用户能参与的优惠活动汇总
服务器·网络·京东云
浅水壁虎4 小时前
任务调度——XXLJOB3(执行器)
java·服务器·前端·spring boot
郝学胜-神的一滴4 小时前
深入理解TCP协议:数据格式与核心机制解析
linux·服务器·网络·c++·网络协议·tcp/ip
济6174 小时前
linux 系统移植(第十三期)---Linux 内核移植(2)- CPU 主频修改--- Ubuntu20.04
linux·运维·服务器
生活很暖很治愈4 小时前
Linux基础指令——【2】
linux·服务器·后端·ubuntu
未来之窗软件服务5 小时前
服务器运维(二十四) SSL数字证书管理续期—东方仙盟练气期
运维·服务器·ssl·仙盟创梦ide·东方仙盟
UP_Continue5 小时前
Linux--进程优先级和进程切换
linux·运维·服务器