首页 > 其他分享 >OS Lab 1.3 pingpong (easy)

OS Lab 1.3 pingpong (easy)

时间:2022-11-25 14:09:30浏览次数:55  
标签:写入 pingpong 管道 fd user easy 进程 参数 OS


1

实验要求


    使用 UNIX 系统调用编写一个程序 pingpong ,在一对管道上实现两个进程之间的通信。父进程应该通过第一个管道给子进程发送一个信息 "ping",子进程接收父进程的信息后打印 ​​"<pid>: received ping"​​​ ,其中是其进程 ID 。然后子进程通过另一个管道发送一个信息 "pong" 给父进程,父进程接收子进程的信息然后打印 ​​"<pid>: received pong"​​ ,然后退出。


2

实验提示


  • 使用 ​​pipe​​ 创建管道。
  • 使用 ​​fork​​ 创建一个子进程。
  • 使用 ​​read​​ 从管道读取信息,使用 ​​write​​ 将信息写入管道。
  • 使用 ​​getpid​​ 获取当前 ​​进程 ID​​ 。
  • 将程序添加到 ​​Makefile​​ 中的 ​​UPROGS​​ 。
  • xv6 上的用户程序具有有限的库函数可供它们使用。你可以在 ​​user/user.h​​ 中查看,除系统调用外其他函数代码位于 ​​user/ulib.c​​ 、​​user/printf.c​​ 、和 ​​user/umalloc.c​​ 中。


3

实验思路


  1. 首先引入头文件 ​​kernel/types.h​​ 和 ​​user/user.h​​ 。
  2. 开始编写 ​​main​​ 函数,定义两个文件描述符 ​​ptoc_fd​​ 和 ​​ctop_fd​​ 数组,创建两个管道, ​​pipe(ptoc_fd)​​ 和 ​​pipe(ctop_fd)​​ ,一个用于父进程传递信息给子进程,另一个用于子进程传递信息给父进程。​​pipe(pipefd)​​ 系统调用会创建管道,并把读取和写入的文件描述符返回到 ​​pipefd​​ 中。​​pipefd[0]​​ 指管道的读取端, ​​pipefd[1]​​ 指管道的写入端。可以使用命令 ​​man pipe​​ 查看手册获取更多内容。
  3. 创建缓冲区字符数组,存放传递的信息。
  4. 使用 ​​fork​​ 创建子进程,子进程的 ​​fork​​ 返回值为 0 ,父进程的 ​​fork​​ 返回子进程的 ​​进程 ID​​ ,所以通过 if 语句就能让父进程和子进程执行不同的代码块。
  5. 编写父进程执行的代码块。使用 ​​write()​​ 系统调用传入三个参数,把字符串 ​​"ping"​​ 写入管道一,第一个参数为管道的写入端文件描述符,第二个参数为写入的字符串,第三个参数为写入的字符串长度。然后调用 ​​wait()​​ 函数等待子进程完成操作后退出,传入参数 0 或者 NULL ,不过后者需要引入头文件 ​​stddef.h​​ 。使用 ​​read()​​ 系统调用传入三个参数,接收从管道二传来的信息,第一个参数为管道的读取端文件描述符,第二个参数为缓冲区字符数组,第三个参数为读取的字符串长度。最后调用 ​​printf()​​ 函数打印当前进程 ID 以及接收到的信息,即缓冲区的内容。
  6. 编写子进程执行的代码块。使用 ​​read()​​ 系统调用传入三个参数,接收从管道一传来的信息,第一个参数为管道的读取端文件描述符,第二个参数为缓冲区字符数组,第三个参数为读取的字符串长度。然后调用 ​​printf()​​ 函数打印当前进程 ID 以及接收到的信息,即缓冲区的内容。最后使用 ​​write()​​ 系统调用传入三个参数,把字符串 ​​"pong"​​ 写入管道二,第一个参数为管道的写入端文件描述符,第二个参数为写入的字符串,第三个参数为写入的字符串长度。
  7. 最后调用 ​​exit()​​ 系统调用使程序正常退出。


4

实验代码


// Lab Xv6 and Unix utilities
// pingpong.c
#include "kernel/types.h"
#include "user/user.h"
#include "stddef.h"

int
main(int argc, char *argv[])
{
int ptoc_fd[2], ctop_fd[2];
pipe(ptoc_fd);
pipe(ctop_fd);
char buf[8];
if (fork() == 0) {
// child process
read(ptoc_fd[0], buf, 4);
printf("%d: received %s\n", getpid(), buf);
write(ctop_fd[1], "pong", strlen("pong"));
}
else {
// parent process
write(ptoc_fd[1], "ping", strlen("ping"));
wait(NULL);
read(ctop_fd[0], buf, 4);
printf("%d: received %s\n", getpid(), buf);
}
exit(0);
}



5

实验结果


    在 ​​Makefile​​​ 文件中, ​​UPROGS​​​ 项追加一行 ​​$U/_pingpong\​​ 。编译并运行 xv6 进行测试。

$ make qemu
...
init: starting sh
$ pingpong
4: received ping
3: received pong
$

退出 xv6 ,运行单元测试检查结果是否正确。

./grade-lab-util pingpong

通过测试样例。

make: 'kernel/kernel' is up to date.
== Test pingpong == pingpong: OK (1.1s)



标签:写入,pingpong,管道,fd,user,easy,进程,参数,OS
From: https://blog.51cto.com/u_15891283/5886610

相关文章