dup函数剖析

来源:互联网 发布:mac 日历订阅链接 编辑:程序博客网 时间:2024/05/20 16:43

dup的作用是复制文件句柄。为了能够一睹dup的真身,不得不提到任务数据结构-----就是我们常说的PCB结构。在linux内核中,此结构定义为struct task_struct。

task_struct有一个文件结构指针数组,数组的元素个数就是进程能够打开的文件句柄的数量最大值。当前进程打开的每个文件都在此数组中占据一个位置。

函数原型:int dup(int oldfd)。oldfd是原句柄,如果复制成功,则返回oldfd句柄的一个副本,此副本与原句柄指向内存中同一个文件节点。

此后通过句柄对文件的操作也会影响到另一个句柄的操作行为。比如通过lseek对副本文件句柄所指文件定位时,原句柄的文件当前指针也会跟着变化。

内核中的任务数据结构有一个长整数类型的变量close_on_exec。通过fork创建子进程后,子进程调用exec类函数运行新程序时,会根据close_on_exec的每个比特位所代表的文件描述符,关闭相应的文件,但是通过dup复制的文件句柄不在此列。源码面前,了无秘密,摘自linux0.11版内核的源码如下:

static int dupfd(unsigned int fd, unsigned int arg)

{

//......

    current->close_on_exec &= ~(1<<arg);              //将对应位置0

    (current->filp[arg] = current->filp[fd])->f_count++; //原句柄与副本句柄所指的文件节点的计数器加1

}

int do_execve(...)

{

//......

    for (i=0 ; i<NR_OPEN ; i++)
        if ((current->close_on_exec>>i)&1)
            sys_close(i);
    current->close_on_exec = 0;

}

dupfd是dup的具体实现。do_execve是exec家族函数的具体实现