注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

BCB-DG's Blog

...

 
 
 

日志

 
 

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

2013-09-24 11:06:57|  分类: Linux |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
来源:Linux社区  作者:ce123

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;
}

我们再来看一下扩展文件描述符表的关键函数alloc_fdtable,其定义如下:

static struct fdtable *alloc_fdtable(int nr)
{
 struct fdtable *fdt = NULL;
 int nfds = 0;
   fd_set *new_openset = NULL, *new_execset = NULL;
 struct file **new_fds;

 fdt = kmalloc(sizeof(*fdt), GFP_KERNEL);
 if (!fdt)
    goto out;
 memset(fdt, 0, sizeof(*fdt));

 nfds = __FD_SETSIZE;  //#define __FD_SETSIZE 1024
            //  #define PAGE_SHIFT  12
            //  #define PAGE_SIZE  (1UL << PAGE_SHIFT)
   /* Expand to the max in easy steps */
   do {
  if (nfds < (PAGE_SIZE * 8))//dfds = 1024
   nfds = PAGE_SIZE * 8;
  else {
   nfds = nfds * 2;
   if (nfds > NR_OPEN)
    nfds = NR_OPEN;
  }
 } while (nfds <= nr);//第一次expand时,nr应该等于32

   new_openset = alloc_fdset(nfds);//分配打开文件位图
   new_execset = alloc_fdset(nfds);
   if (!new_openset || !new_execset)
    goto out;
 fdt->open_fds = new_openset;
 fdt->close_on_exec = new_execset;
 fdt->max_fdset = nfds;//更新max_fdset值,此时这个值为32k

 nfds = NR_OPEN_DEFAULT;//nfds = 32
 /*
  * Expand to the max in easy steps, and keep expanding it until
  * we have enough for the requested fd array size.
  */
 do {
#if NR_OPEN_DEFAULT < 256
  if (nfds < 256)
   nfds = 256;//nfds = 256(32->256->1024)
   //无法超过1024,因为在最开始的就进行了检查,一定要小于current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
  else
#endif
  if (nfds < (PAGE_SIZE / sizeof(struct file *)))
   nfds = PAGE_SIZE / sizeof(struct file *);
  else {
   nfds = nfds * 2;
   if (nfds > NR_OPEN)
    nfds = NR_OPEN;
    }
 } while (nfds <= nr);
 new_fds = alloc_fd_array(nfds);//分配文件描述符数组
 if (!new_fds)
  goto out;
 fdt->fd = new_fds;
 fdt->max_fds = nfds;//更新max_fds
 fdt->free_files = NULL;
 return fdt;
out:
   if (new_openset)
    free_fdset(new_openset, nfds);
   if (new_execset)
    free_fdset(new_execset, nfds);
 kfree(fdt);
 return NULL;
}

alloc_fd_array和alloc_fdset采用kmalloc或者vmalloc进行内存分配。

  评论这张
 
阅读(673)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017