05.04 Shell 启动的程序的三大标准文件是同一个文件

#include <errno.h>
#include <fcntl.h>
#include <linux/kcmp.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>

int main() {
    pid_t pid = getpid(); /* always successful */
    int ret = syscall(SYS_kcmp, pid, pid, KCMP_FILE, 0, 1);
    int ec = errno;
    if (ec) {
        perror("kcmp");
        return 1;
    }
    printf("kcmp returns %d\n", ret);
}

其中,kcmp 系统调用可以用来比较两个进程的资源大小(0 等于,1 小于,2 等于,3 不相等但无法确定大小)。输出:

kcmp returns 0

这说明此文件在终端中运行时,标准输入流和输出流使用的是相同的打开文件项(事实上就连标准错误流都是用的同一个文件项)。一个程序的标准输入输出使用不会产生冲突吗?查看一下当前 shell 的信息:

(py310) xxx ~ $ ls -lh /proc/self/fd/0
lrwx------ 1 xxx xxx 64 May 16 16:49 /proc/self/fd/0 -> /dev/pts/0
(py310) xxx ~ $ ls -lh /proc/$$/fd/0
lrwx------ 1 xxx xxx 64 May 16 16:43 /proc/387/fd/0 -> /dev/pts/0
(py310) xxx ~ $ cat /proc/$$/fdinfo/0
pos:    0
flags:  0100002
mnt_id: 115
ino:    3
(py310) xxx ~ $ cat /proc/$$/fdinfo/1
pos:    0
flags:  0100002
mnt_id: 115
ino:    3
(py310) xxx ~ $ file /proc/$$/fd/0
/proc/387/fd/0: symbolic link to /dev/pts/0
(py310) xxx ~ $ file $(readlink -f /proc/$$/fd/0)
/dev/pts/0: character special (136/0)
  • 从两次 ls 可以看出 shell 把和自己关联的文件分给了子进程。
  • 从两次 file 看出这个关联文件是一种字符设备。
  • 从两次 cat 可以看出字符设备的 pos 总是 0,因此文件偏移量不会干扰读写。

学完 62 章终端和 64 章伪终端就明白为什么了。