歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux內核

Linux內核中的dup系統調用

Linux內核版本:2.6.14

dup系統調用的服務例程為sys_dup函數,定義在fs/fcntl.c中。sys_dup()的代碼也許稱得上是最簡單的之一了,但是就是這麼一個簡單的系統調用,卻成就了linux系統最著名的一個特性:輸入/輸出重定向。sys_dup()的主要工作就是用來“復制”一個打開的文件號,並使兩個文件號都指向同一個文件,下面我們來分析一下它的代碼。

1.sys_dup源碼分析

asmlinkage long sys_dup(unsigned int fildes)//sys_dup函數的參數,即fildes,是文件描述符fd
{
 int ret = -EBADF;
 struct file * file = fget(fildes);//通過文件描述符找到對應的文件


 if (file)
  ret = dupfd(file, 0);//分配一個新的文件描述符fd,並將fd和file聯系起來
 return ret;
}

1.1fget(fildes)

struct file fastcall *fget(unsigned int fd)
{
 struct file *file;
 struct files_struct *files = current->files;//獲得當前進程的打開文件表


 rcu_read_lock();
 file = fcheck_files(files, fd);//根據fd從打開文件表files裡取出相應的file結構變量
 if (file) {
  if (!rcuref_inc_lf(&file->f_count)) {  //增加引用
   /* File object ref couldn't be taken */
   rcu_read_unlock();
   return NULL;
  }
 }
 rcu_read_unlock();


 return file;
}
static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
{
 struct file * file = NULL;
 struct fdtable *fdt = files_fdtable(files);


 if (fd < fdt->max_fds)
  file = rcu_dereference(fdt->fd[fd]);
 return file;
}

1.2dupfd(file, 0)

static int dupfd(struct file *file, unsigned int start)
{
 struct files_struct * files = current->files;
 struct fdtable *fdt;
 int fd;


 spin_lock(&files->file_lock);
 fd = locate_fd(files, file, start);//分配文件描述符
 if (fd >= 0) {
  /* locate_fd() may have expanded fdtable, load the ptr */
  fdt = files_fdtable(files);//獲得文件描述符表
  FD_SET(fd, fdt->open_fds);//設置打開文件標記
  FD_CLR(fd, fdt->close_on_exec);
  spin_unlock(&files->file_lock);
  fd_install(fd, file);//建立fd和file的聯系,之後通過fd就可以找到file
 } else {
  spin_unlock(&files->file_lock);
  fput(file);
 }


 return fd;
}

2.內核初始化中的相關源碼分析

static int init(void * unused)
{
 ...
 if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
  printk(KERN_WARNING "Warning: unable to open an initial console.\n");
 //打開控制台,這樣init進程就擁有一個控制台,並可以從中讀取輸入信息,也可以向其中寫入信息

 (void) sys_dup(0);//調用dup打開/dev/console文件描述符兩次,這樣控制太設備也可以供表述輸出和標准錯誤使用(文件描述符為1和2)
 (void) sys_dup(0);
 //假設sys_open((const char __user *) "/dev/console", O_RDWR, 0) 成功執行,init進程就擁有3個文件描述符(標准輸入、標准輸出和標准錯誤)
 ...
}

Copyright © Linux教程網 All Rights Reserved