操作系统

形象的理解dup和dup2函数
作者 HonestQiao 2009年08月27日 16:00

    相信大部分在Unix/Linux下编程的程序员手头上都有《Unix环境高级编程》(APUE)这本超级经典巨著。作者在该书中讲解dup/dup2之前曾经讲过“文件共享”,这对理解dup/dup2还是很有帮助的。这里做简单摘录以备在后面的分析中使用:
    Stevens said:
    (1) 每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表,可将视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
    (a) 文件描述符标志。
    (b) 指向一个文件表项的指针。
    (2) 内核为所有打开文件维持一张文件表。每个文件表项包含:
    (a) 文件状态标志(读、写、增写、同步、非阻塞等)。
    (b) 当前文件位移量。
    (c) 指向该文件v节点表项的指针。
    图示:
    文件描述符表
    ------------
    fd0 0 | p0 -------------> 文件表0 ---------> vnode0
    ------------
    fd1 1 | p1 -------------> 文件表1 ---------> vnode1
    ------------
    fd2 2 | p2
    ------------
    fd3 3 | p3
    ------------
    ... ...
    ... ...
    ------------
    一、单个进程内的dup和dup2
    假设进程A拥有一个已打开的文件描述符fd3,它的状态如下:
    进程A的文件描述符表(before dup2)
    ------------
    fd0 0 | p0
    ------------
    fd1 1 | p1 -------------> 文件表1 ---------> vnode1
    ------------
    fd2 2 | p2
    ------------
    fd3 3 | p3 -------------> 文件表2 ---------> vnode2
    ------------
    ... ...
    ... ...
    ------------
    经下面调用:
    n_fd = dup2(fd3, STDOUT_FILENO);后进程状态如下:
    进程A的文件描述符表(after dup2)
    ------------
    fd0 0 | p0
    ------------
    n_fd 1 | p1 ------------
    ------------ \
    fd2 2 | p2 \
    ------------ _\|
    fd3 3 | p3 -------------> 文件表2 ---------> vnode2
    ------------
    ... ...
    ... ...
    ------------
    解释如下:
    n_fd = dup2(fd3, STDOUT_FILENO)表示n_fd与fd3共享一个文件表项(它们的文件表指针指向同一个文件表项),n_fd在文件描述符表中的位置为 STDOUT_FILENO的位置,而原先的STDOUT_FILENO所指向的文件表项被关闭,我觉得上图应该很清晰的反映出这点。按照上面的解释我们就可以解释CU中提出的一些问题:
    (1) "dup2的第一个参数是不是必须为已打开的合法filedes?" -- 答案:必须。
    (2) "dup2的第二个参数可以是任意合法范围的filedes值么?" -- 答案:可以,在Unix其取值区间为[0,255]。
    另外感觉理解dup2的一个好方法就是把fd看成一个结构体类型,就如上面图形中画的那样,我们不妨把之定义为:
    struct fd_t {
    int index;
    filelistitem *ptr;
    };
    然后dup2匹配index,修改ptr,完成dup2操作。
    在学习dup2时总是碰到“重定向”一词,上图完成的就是一个“从标准输出到文件的重定向”,经过dup2后进程A的任何目标为STDOUT_FILENO的I/O操作如printf等,其数据都将流入fd3所对应的文件中。下面是一个例子程序:
    #define TESTSTR "Hello dup2\n"
    int main() {
    int fd3;
    fd3 = open("testdup2.dat", 0666);
    if (fd < 0) {
    printf("open error\n");
    exit(-1);
    }
    if (dup2(fd3, STDOUT_FILENO) < 0) {
    printf("err in dup2\n");
    }
    printf(TESTSTR);
    return 0;
    }
    其结果就是你在testdup2.dat中看到"Hello dup2"。

打开APP阅读全文

形象的理解dup和dup2函数

形象的理解dup和dup2函数

长按识别二维码 进入IT168查看全文

请长按保存图片
{{data.thematic.text}}

相关文章

加载中...

分享到

请使用浏览器的分享功能
分享到微信等