总结了Linux操作系统中I/O重定向问题
涉及open、close、dup、dup2系统调用
1. I/O重定向
1.1 Linux中的文件描述符fd:
文件描述符代表一个文件,他是进程级的。在进程PCB中存在着一张文件描述符表,也可以叫做打开文件描述符表。这张表每个进程都会有且为进程独有,所以它是进程级的。这张表上的每一个表项都由两个部分组成,文件描述符标志以及一个文件指针。其中文件描述符标志也就是我们所使用的文件描述符fd
,也可以将其看做是这张表的下标。
内核(kernel)利用文件描述符(fd)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。文件描述符这一概念往往只适用于UNIX
、Linux
这样的操作系统。
在Linux下,当一个用户进程被创建的时候,系统会自动为该进程创建三个数据流:stdin/stdout/stderr
-
stdin
的文件描述符是0
-
stdout
的文件描述符是1
-
stderr
的文件描述符是2
由于linux中的一些涉及底层的程序编写往往会围绕着文件描述符展开,因此我们只需要将其他文件(如一个新打开的文件)的文件描述符替换为0/1/2
(即替换掉stdin/stdout/stderr
的文件描述符),就可以完成I/O重定向。使得原本针对标准输入输出流文件进行的操作变为针对其他文件的输入输出操作。
1.2 重定向标准输入
用一个新打开的文件替换文件描述符0
(原本是stdin
的文件描述符),那么输入将来自该新文件而不是标准输入流
1.2.1 close系统调用
close()
函数关闭文件描述符(使之成为未使用的文件描述符,后面其他文件可以使用该fd)并释放相应的内核资源,成功返回0,出错返回-1
int close(int fd);
参数fd
是要关闭的文件描述符。需要说明的是,当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close
关闭,所以即使用户程序不调用close,在终止时内核也会自动关闭它打开的所有文件。但是对于一个长年累月运行的程序(比如网络服务器),打开的文件描述符一定要记得关闭,否则随着打开的文件越来越多,会占用大量文件描述符和系统资源。
1.2.2 open系统调用
open()
函数会打开一个文件,并使用最小的未使用的文件描述符数值作为文件描述符(因此一般是从3开始,然后4,5,6一直下去)成功返回文件描述符,失败返回-1
int open(const char *pathname, int flags,mode_t mode);
-
参数
path
是要打开或者要创建的文件路径 -
参数
flags
用于指定文件的打开/创建模式,这个参数可由以下常量(定义于 fcntl.h)通过逻辑或构成:O_RDONLY
(只读)、O_WRONLY
(只写)、O_RDWR
(读写)、O_CREAT
(如果文件不存在则创建)、O_APPEND
(追加)等 -
第三个参数
mode
仅当创建新文件时才使用,用于指定文件的访问权限位,如八进制数字如0777
,表示文件所有者、该文件用户组、其他用户都有可读可写可执行权限。
1.2.3 使用close与open系统调用完成重定向标准输入
文本文档log.txt
the num is 123
源文件main.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>