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

Linux內核中的文件描述符(六)--fd的分配--expand_files

Kernel version:2.6.14

CPU architecture:ARM920T

我們先貼出expand_files函數的源碼:

int expand_files(struct files_struct *files, int nr)
{
 int err, expand = 0;
 struct fdtable *fdt;

 fdt = files_fdtable(files);
 if (nr >= fdt->max_fdset || nr >= fdt->max_fds) {  //我們在前面的文章中已經分析過,初始時max_fdset = 1024,max_fds = 32
  if (fdt->max_fdset >= NR_OPEN ||  //#define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */
   fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) {
   err = -EMFILE;  //max_fdset和max_fds都不能大於 NR_OPEN,否則返回 -EMFILE,即打開太多的文件

   goto out;
  }
  expand = 1;
  if ((err = expand_fdtable(files, nr)))//真正進行擴展
   goto out;
 }
 err = expand;
out:
 return err;
}

expand_files函數進行一些檢查後調用expand_fdtable進行文件描述符表的擴展,下面分析expand_fdtable函數。

static int expand_fdtable(struct files_struct *files, int nr)
 __releases(files->file_lock)
 __acquires(files->file_lock)
{
 int error = 0;
 struct fdtable *fdt;
 struct fdtable *nfdt = NULL;

 spin_unlock(&files->file_lock);
 nfdt = alloc_fdtable(nr);//根據nr重新創建一個新的fdtable
 if (!nfdt) {
  error = -ENOMEM;
  spin_lock(&files->file_lock);
  goto out;
 }

 spin_lock(&files->file_lock);
 fdt = files_fdtable(files);
 /*
  * Check again since another task may have expanded the
  * fd table while we dropped the lock
  */
 if (nr >= fdt->max_fds || nr >= fdt->max_fdset) { //nr值必須大於max_fds和max_fdset值,這裡再次進行檢查是防止另一個進程進行了expand
  copy_fdtable(nfdt, fdt); //將舊的fdtable中的內容拷貝至新的fdtable
 } else {
  /* Somebody expanded while we dropped file_lock */
  spin_unlock(&files->file_lock);
  __free_fdtable(nfdt);
  spin_lock(&files->file_lock);
  goto out;
 }
 rcu_assign_pointer(files->fdt, nfdt);//用新的fdtable替換舊的fdtable  
 free_fdtable(fdt);//釋放舊的fdtable 
out:
 return error;
}

Copyright © Linux教程網 All Rights Reserved