Xv6 管道

1,225 阅读1分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

Xv6 管道

参考: xv6-riscv-book 1.3 Pipes

pipe

Xv6 系统调用 pipe() 来创建管道。管道类似于 Go 语言中的 chan。在 Shell 里我们用 | 表示管道,对于命令: echo "hello world" | wc,可以用如下代码实现:

// upipe.c

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

int main() {
	int p[2];  // file descriptors for the pipe
	
	char *argv[2];
	argv[0] = "wc";
	argv[1] = 0;  // NULL

	pipe(p);  // creates a new pipe: records the read and write file descriptors in the array p

	if (fork() == 0) {
		// redirection
		close(0);
		dup(p[0]);  // stdin = <- pipe

		close(p[0]);
		close(p[1]);

		exec("wc", argv);
	} else {
		close(p[0]);

		write(p[1], "hello world\n", 12);  // pipe <- str

		close(p[1]);
	}

	exit(0);
}

编译运行:

$ upipe
1 2 12

Xv6 sh 里的管道处理实现其实就和这段代码类似:fork 两个进程,分别重定向标准输出 or 输入、运行管道左右两边的命令。详见 user/sh.c:100

管道 V.S. 临时文件

用管道与用临时文件,使用上似乎区别不大:

# 管道
echo "hello world" | wc
# 临时文件
echo hello world >/tmp/xyz; wc </tmp/xyz

但管道更好:

  • 管道会自动清理(临时文件要手动删除)
  • 管道可以放任意长度的数据流(临时文件需要有足够的磁盘空间)
  • 管道可以并行运行(临时文件只能一个运行完,第二个再开始)
  • 在处理进程间通信问题时,管道的阻塞式读写比用非阻塞的临时文件方便。

EOF


By CDFMLR 2021-02-20

echo "See you. 🪐"

顶部图片来自于小歪API,系随机选取的图片,仅用于检测屏幕显示的机械、光电性能,与文章的任何内容及观点无关,也并不代表本人局部或全部同意、支持或者反对其中的任何内容及观点。如有侵权,联系删除。