上一篇介绍了I/O重定向原理和实现后,这篇主要介绍一下常用的shell命令是如何利用IO重定向的。分析过程主要利用strace观察各个命令调用的系统调用的过程。
echo
利用如下命令可以看到一个echo命令在执行过程中的关键步骤,简化过程如下
strace bash -c "echo 11 > /test"
execve("/bin/bash", ["bash", "-c", "echo 11 > /test"], [/* 21 vars */]) = 0
open("/test", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fcntl(1, F_DUPFD, 10) = 10
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
write(1, "11\n", 3) = 3
dup2(10, 1) = 1
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
exit_group(0) = ?
上面过程可以利用如下图表示

仔细分析上图可以发现结构有趣的点
1、就是test文件被主动打开后就没有被主动关闭,根据上一篇介绍,可知这个文件是在dup2这个系统调用内部,内核关闭了。(这是今天遇到的一个坑,mark一下)
2、echo是bash的内建命令,内部并未调用fork去执行其他可执行程序,同时由于是内建命令,其IO重定向也比较简单直接利用dup系统调用即可。
cat
介绍cat主要是想对比一下shell中非内建命令如何利用IO重定向,分析命令如下
strace -f bash -c "cat 11 > 12"
该命令的执行过程如下
execve("/bin/bash", ["bash", "-c", "cat 11 > 12"], [/* 21 vars */]) = 0
...
access("/bin/cat", R_OK) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff6cb473a10) = 43237
[pid 43237] open("12", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
[pid 43237] dup2(3, 1) = 1
[pid 43237] close(3) = 0
[pid 43237] execve("/bin/cat", ["cat", "11"], [/* 20 vars */]) = 0
[pid 43237] open("11", O_RDONLY) = 3
[pid 43237] read(3, "11\n", 65536) = 3
[pid 43237] write(1, "11\n", 3) = 3
[pid 43237] read(3, "", 65536) = 0
[pid 43237] close(3) = 0
[pid 43237] close(1) = 0
[pid 43237] close(2) = 0
[pid 43237] exit_group(0) = ?
这个过程也可以用下图表示,待补充
网友评论