dup与dup2系统调用
以下代码摘自Linux 0.11,虽然代码已经过时,但是它的实现非常直观,简单,对于理解dup的实现有着很大的价值和帮助。通过这段代码,很容易理解dup背后的思想。
//// 复制文件句柄(描述符)。——fs/fcntl.c
// 参数fd 是欲复制的文件句柄,arg 指定新文件句柄的最小数值。
// 返回新文件句柄或出错码。
static int
dupfd (unsigned int fd, unsigned int arg)
{
// 如果文件句柄值大于一个程序最多打开文件数NR_OPEN,或者该句柄的文件结构不存在,则出错,
// 返回出错码并退出。
if (fd >= NR_OPEN || !current->filp[fd])
return -EBADF;
// 如果指定的新句柄值arg 大于最多打开文件数,则出错,返回出错码并退出。
if (arg >= NR_OPEN)
return -EINVAL;
// 在当前进程的文件结构指针数组中寻找索引号大于等于arg 但还没有使用的项。
while (arg < NR_OPEN)
if (current->filp[arg])
arg++;
else
break;
// 如果找到的新句柄值arg 大于最多打开文件数,则出错,返回出错码并退出。
if (arg >= NR_OPEN)
return -EMFILE;
// 在执行时关闭标志位图中复位该句柄位。也即在运行exec()类函数时不关闭该句柄。
current->close_on_exec &= ~(1 << arg);
// 令该文件结构指针等于原句柄fd 的指针,并将文件引用计数增1。
(current->filp[arg] = current->filp[fd])->f_count++;
return arg; // 返回新的文件句柄。
}
//// 复制文件句柄系统调用函数。
// 复制指定文件句柄oldfd,新句柄值等于newfd。如果newfd 已经打开,则首先关闭之。
int
sys_dup2 (unsigned int oldfd, unsigned int newfd)
{
sys_close (newfd); // 若句柄newfd 已经打开,则首先关闭之。
return dupfd (oldfd, newfd); // 复制并返回新句柄。
}
//// 复制文件句柄系统调用函数。
// 复制指定文件句柄oldfd,新句柄的值是当前最小的未用句柄。
int
sys_dup (unsigned int fildes)
{
return dupfd (fildes, 0);
}
// 参数fd 是欲复制的文件句柄,arg 指定新文件句柄的最小数值。
// 返回新文件句柄或出错码。
static int
dupfd (unsigned int fd, unsigned int arg)
{
// 如果文件句柄值大于一个程序最多打开文件数NR_OPEN,或者该句柄的文件结构不存在,则出错,
// 返回出错码并退出。
if (fd >= NR_OPEN || !current->filp[fd])
return -EBADF;
// 如果指定的新句柄值arg 大于最多打开文件数,则出错,返回出错码并退出。
if (arg >= NR_OPEN)
return -EINVAL;
// 在当前进程的文件结构指针数组中寻找索引号大于等于arg 但还没有使用的项。
while (arg < NR_OPEN)
if (current->filp[arg])
arg++;
else
break;
// 如果找到的新句柄值arg 大于最多打开文件数,则出错,返回出错码并退出。
if (arg >= NR_OPEN)
return -EMFILE;
// 在执行时关闭标志位图中复位该句柄位。也即在运行exec()类函数时不关闭该句柄。
current->close_on_exec &= ~(1 << arg);
// 令该文件结构指针等于原句柄fd 的指针,并将文件引用计数增1。
(current->filp[arg] = current->filp[fd])->f_count++;
return arg; // 返回新的文件句柄。
}
//// 复制文件句柄系统调用函数。
// 复制指定文件句柄oldfd,新句柄值等于newfd。如果newfd 已经打开,则首先关闭之。
int
sys_dup2 (unsigned int oldfd, unsigned int newfd)
{
sys_close (newfd); // 若句柄newfd 已经打开,则首先关闭之。
return dupfd (oldfd, newfd); // 复制并返回新句柄。
}
//// 复制文件句柄系统调用函数。
// 复制指定文件句柄oldfd,新句柄的值是当前最小的未用句柄。
int
sys_dup (unsigned int fildes)
{
return dupfd (fildes, 0);
}