进程间通信——重定向描述符表

网友投稿 677 2022-05-28

在命令行运行程序时,可以用“>"运算符把标准输出重定向到文件:

~/Desktop/Mc$ echo "hello world" > log.txt ~/Desktop/Mc$ tail -f log.txt hello world

1

2

3

标准输入、标准输出、标准错误是三大默认数据流,除此之外还有其他形式的数据流,如文件连接和网络连接也属于数据流。数据流就是流动的数据,数据从一个进程流出,然后流入另一个进程。

重定向进程的输出,相当于改变进程发送数据的方向。如上面的例子,原本标准输出会把数据发送到屏幕,现在让它把数据发送到文件。

进程含有它正在运行的程序,还有栈和堆空间。除此之外,进程还需要记录数据流的连向,比如标准输出连到了哪里。这些记录记在哪里呢?答案就是描述符表。进程用文件描述符表示数据流,所谓的描述符其实就是一个数字。进程会把文件描述符和对应的数据流保存在描述符表中。

描述符表

描述符表的一列是文件描述符号,另一列是它们对应的数据流。虽然名字叫文件描述符,但它们不一定连接硬盘上的某个文件,也可能连接键盘、屏幕、文件指针、网络。

描述符表的前三项是不会变的:0号标准输入、1号标准输出、2号标准错误。其他项要么为空,要么连接进程打开的数据流。比如程序在打开文件进行读写时,就会占用其中一项。描述符表的大小是从0到255号。

创建进程以后,标准输入连接到键盘,标准输出和标准错误连接到屏幕。它会保持这样的连接,直到有人把它们重定向到了其他地方。

重定向就是替换数据流

标准输入/输出/错误在描述符表中的位置是固定的,但它们指向的数据流是可以改变的。例如想重定向标准输出,只需要修改表中1号描述符对应的数据流就OK了。

所有向标准输出发送数据的函数会先查看描述符表,看1号描述符指向哪条数据流,然后再把数据写到这条数据流中,printf()函数就是这样。

进程可以重定向自己

在命令行中可以用“>“和”<"运算符重定向程序。进程也能重定向它们自己,只需修改描述符表。只需要两步就可以实现:

1.fileno()返回文件描述符号

每打开一个文件,操作系统都会在描述符表中新注册一项。假设我们打开了log.txt文件:

FILE *my_file = fopen("log.txt","w");

1

操作系统会打开log.txt文件,然后返回一个指向它的指针,操作系统还会遍历描述符表找空项,把新文件注册在其中。

int descriptor = fileno(my_file);

1

在失败时不返回-1的函数很少,fileno()就是其中之一。只要你把打开文件的文件指针传给fileno(),它就一定会返回描述符编号。

2.dup2()复制数据流

每次打开文件都会使用描述符表中新的一项。但如果你想修改某个已经注册过的数据流,比如让1号文件描述符重新指向其他数据流,就可以用dup2()函数来实现,dup2()可以复制数据流,假设我们在3号文件描述符中注册了log.txt文件指针,下面代码就可以同时把文件指针连接到1号描述符:

dup2(3,1);

1

虽然log.txt文件只有一个,与它相连的数据流也只有一个,但是数据流(FILE *)同时注册在文件描述符1和3中。所以标准输出都会被重定向到文件log.txt中。

我们看一个完整的实例:

#include #include #include #include int main(){ FILE *my_file = fopen("log.txt","w"); int descriptor = fileno(my_file); dup2(descriptor,1); printf("Hello world,I love you!\n"); return 0; }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

编译运行:

~/Desktop/MyC$ gcc test4.c -o test4 ~/Desktop/MyC$ ./test4 ~/Desktop/MyC$ tail -f log.txt Hello world,I love you!

1

2

进程间通信——重定向、描述符表

3

4

用管道连接输入与输出,符号“|”表示管道(pipe),它能连接一个进程的标准输出与另一个进程的标准输入。

如:

~/Desktop/MyC$ ls /usr/include | grep stdio stdio_ext.h stdio.h

1

2

3

ls程序的标准输出会连接到grep程序的标准输入。

谢谢阅读!

任务调度

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Vue进阶(八十七):VUE输入框事件监听blur与change的差异
下一篇:日交易额百亿级交易系统的超轻量日志实现
相关文章