以下代碼摘自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);
}