[Chapter10] 对重定向的理解

常用的重定向如who->userlist.txt将who的输出定向到文件userlist.txt,这是如何做到的呢?

who的默认输出对象是标准IO中的stdout,文件描述符为1,而重定向所做的事情是将文件描述符1从默认的tty设备文件移开,而重新分配给其他文件,在本例中为userlist.txt,这样who在向文件描述符1输出用户清单时就会输出到userlist.txt中。

同理,对于输入数据的重定向sort<pricelist.txt来说,被重定向的就是sort的输入源,sort的默认输入源的文件描述符为0,sort从描述符为0的文件——tty输入读取数据,而重定向所做的就是将0从tty输入移开,而分配给pricelist.txt,这样sort就会从pricelist.txt文件中读取数据进行排序,然后输出。

重定向到文件的小结:

(1)标准输入、输出、错误分别对应于文件描述符0、1、2;

(2)内核总是使用最低可用文件描述符;

(3)文件描述符集合通过exec调用传递,且不会改变。

shell的重定向功能是通过在fork和exec中间重定向标准输入、输出、错误来实现,如下面例程所示。

实际上使用管道的who | sort的也是一种重定向,只不过不是重定向到文件,而是重定向到另一个进程,这样就可以实现进程间的交互,这是通过将进程的输入输出重定向到管道来实现的。另外,socket的原理其实和管道很相似。

/* whotofile.c - fork a child, redirect stdout to file then execute who */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
    int fd;
    int pid;

    printf( "about to execute who
" );
    pid = fork();

    if( pid == 0 )         //这里是在子进程中做的,也可以不fork子进程直接做,见下一个例程
    {
        close( 1 );             //先关闭文件描述符1,使得最低文件描述符变为1
        creat( "file", 644 );   //在create一个新文件时会使用最低文件描述符
        execlp( "who", "who", NULL );//执行execlp程序时是在同一进程中,因此继承文件描述符
    }
    else
    {
        wait( NULL );
        printf( "who execute finished!
" );
    }

    return 0;
}

使用dup2的方法实现重定向:

/* stdinredir3.c - redirect stdin to file by "open-dup2-close" */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fd;
    char line[100];

    fgets( line, 100, stdin ); printf( "%s", line );
    
    fd = open( "/etc/passwd", O_RDONLY );
    if( fd == -1 )
        perror( "can open" );
    dup2( fd, 0 );
    close( fd );

    fgets( line, 100, stdin ); printf( "%s", line );
    fgets( line, 100, stdin ); printf( "%s", line );
    fgets( line, 100, stdin ); printf( "%s", line );

    return 0;
}
原文地址:https://www.cnblogs.com/uestcliming666/p/13140806.html