Chinaunix首页 | 论坛 | 博客
  • 博客访问: 26181
  • 博文数量: 15
  • 博客积分: 415
  • 博客等级: 下士
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-05 20:42
文章分类

全部博文(15)

文章存档

2011年(9)

2010年(6)

我的朋友

分类: LINUX

2010-12-17 15:24:13

当个进程内使用dup()/dup2()实现重定向
 

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

int main(void)
{
    int fd_file = -1;
    int oldfd = -1;

    fd_file = open("./test.txt", O_CREAT|O_RDWR);
    if(fd_file == -1){
        printf("open file error \n");
        return -1;
    }else{
        printf("fd_file is %d\n", fd_file);
    }

    oldfd = dup(1);
    printf("oldfd is %d\n", oldfd);
    //redirect fd for STDOUT to fd for test.txt
    //after redirecting stdout to test.txt, content should be output to

    dup2(fd_file, 1); 

    //STDOUT now will be output to test.txt
    printf("This should be written to the test.txt\n");


    dup2(oldfd, 1);//restore fd for STDOUT
    printf("This should be written to the terminal\n");
    close(oldfd);
    close(fd_file);

    return 0;
}


程序输出如下

./a.out
fd_file is 3
oldfd is 4
This should be written to the terminal
cat test.txt
This should be written to the test.txt

每个进程都有一个文件描述符表,每个表项中都有指向对应文件的指针,进程在获取描述符时总是获得"当前所有可用描述符中值最小的"那个.注意,在调用dup2时,如果newfd指向的文件没有和其他描述符关联,那么该文件会被关闭.可以用下面的示意图加深对dup()/dup2()的理解

after invoking open()
 fd   fp            opened file
---------------------------------
| 0 | p0  |----------->STDIN
-----------
| 1 | p1  |----------->STDOUT
-----------
| 2 | p2  |----------->STDERR
-----------
| 3 | p3  |----------->test.txt
-----------

after invoking dup()
 fd   fp            opened file
---------------------------------
| 0 | p0  |----------->STDIN
-----------
| 1 | p1  |----------->STDOUT
-----------      |
| 2 | p2  |----------->STDERR
-----------      |
| 3 | p3  |----------->test.txt
-----------      |
| 4 | p4  |------
-----------

after invoking first dup2()
 fd   fp            opened file
---------------------------------
| 0 | p0  |----------->STDIN
-----------
| 1 | p1  |---   ----->STDOUT
-----------   |  |
| 2 | p2  |----------->STDERR
-----------   |  |
| 3 | p3  |----------->test.txt
-----------      |
| 4 | p4  |------
-----------

after invoking second dup2()
 fd   fp            opened file
---------------------------------
| 0 | p0  |----------->STDIN
-----------
| 1 | p1  |----------->STDOUT
-----------      |
| 2 | p2  |----------->STDERR
-----------      |
| 3 | p3  |----------->test.txt
-----------      |
| 4 | p4  |------
-----------

after invoking close() twice
 fd   fp            opened file
---------------------------------
| 0 | p0  |----------->STDIN
-----------
| 1 | p1  |----------->STDOUT
-----------     
| 2 | p2  |----------->STDERR
-----------     

 

下面是一个从网上找来的例子,通过pipe()/dup()实现了父子进程间的通信

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int cpid = -1;
    int fds[2];

    pipe(fds);

    cpid = fork();
    if(cpid == 0){
        //child
        close(1);//close stdout
        close(fds[0]);
        dup2(fds[1], 1);//redirect stdout to fds[1]
        execlp("ls", "ls", "-l", (const char *)NULL);
    }else if(cpid > 0){
        //parent
        close(0);//close stdin
        close(fds[1]);
        dup2(fds[0], 0);//redirect stdin to fds[0]
        execlp("grep", "grep", "sh", (const char *)NULL);
    }else{
        printf("fork error\n");
        return -1;
    }
    return 0;
}

程序输出如下

./a.out
-rwxr-xr-x 1 jsun jsun       3899 Sep  7 16:17 c_rehash
-rwxrwxrwx 1 jsun jsun       4718 Sep  8 09:41 hash.sh
-rwxr-xr-x 1 jsun jsun       4165 Sep 14 18:03 hash_final.sh
-rw-r--r-- 1 jsun jsun         80 Sep  8 09:41 shash.sh

可以用下面的示意图表示上述程序中父子进程文件描述符表的变化,pfd表示父进程的文件描述符,pfp表示父进程的文件指针;cfp和cfd表示子进程的文件指针和文件描述符.

after pipe()
 pfd  pfp            opened file        cfp  cfd
--------------------------------------------------
| 0 | p0  |----------->STDIN
-----------                    
| 1 | p1  |----------->STDOUT
-----------                        
| 2 | p2  |----------->STDERR
-----------                 
| 3 | p3  |----------->a pipe node       this fd(fds[0]) is for reading
-----------       |
| 4 | p4  |--------                      this fd(fds[1]) is for writing
-----------


after fork()
 pfd  pfp            opened file            cfp  cfd
------------------------------------------------------
| 0 | p0  |----------->STDIN<--------------| p0 | 0  |
-----------                                -----------
| 1 | p1  |----------->STDOUT<-------------| p1 | 1  |
-----------                                -----------
| 2 | p2  |----------->STDERR<-------------| p2 | 2  |
-----------                                -----------
| 3 | p3  |----------->a pipe node<--------| p3 | 3  |
-----------       |                   |    -----------
| 4 | p4  |--------                   -----| p4 | 4  |
-----------                                -----------


after child close() and dup2()
 pfd  pfp            opened file            cfp  cfd
------------------------------------------------------
| 0 | p0  |----------->STDIN<--------------| p0 | 0  |
-----------                                -----------
| 1 | p1  |----------->STDOUT         -----| p1 | 1  |
-----------                           |    -----------
| 2 | p2  |----------->STDERR<-------------| p2 | 2  |
-----------                           |    -----------
| 3 | p3  |----------->a pipe node<----    | p3 | 3  |
-----------       |                   |    -----------
| 4 | p4  |--------                   -----| p4 | 4  |
-----------                                -----------


after parent close() and dup2()
 pfd  pfp            opened file            cfp  cfd
------------------------------------------------------
| 0 | p0  |------      STDIN<--------------| p0 | 0  |
-----------     |                          -----------
| 1 | p1  |----------->STDOUT         -----| p1 | 1  |
-----------     |                     |    -----------
| 2 | p2  |----------->STDERR<-------------| p2 | 2  |
-----------     |                     |    -----------
| 3 | p3  |----------->a pipe node<----    | p3 | 3  |
-----------                           |    -----------
| 4 | p4  |                           -----| p4 | 4  |
-----------                                -----------

至此,父进程的标准输入被重定向到pipe node的读端,子进程的标准输出被重定向到pipe node的写端.该程序中并没有在处理结束后恢复父子进程的标准输入和标准输出,仅仅用于演示.

阅读(836) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~