Linux内核中的文件描述符:fd的分配--get_unused_fd

Neysa ·
更新时间:2024-09-21
· 833 次阅读

  在Linux内核中主要有两个函数涉及到文件描述符的分配:get_unused_fd和locate_fd。本文主要讲解get_unused_fd,将会在下一篇文章中介绍locate_fd。首先给出get_unused_fd的定义(fs/open.c):

int get_unused_fd(void) {  struct files_struct * files = current->files;//获得当前进程的打开文件列表files  int fd, error;  struct fdtable *fdt;

   error = -EMFILE;  spin_lock(&files->file_lock);

repeat:  fdt = files_fdtable(files);//获得文件描述符位图结构   fd = find_next_zero_bit(fdt->open_fds->fds_bits,     fdt->max_fdset,     fdt->next_fd); //find_next_zero_bit函数在文件描述符位图fds_bits中从next_fd位开始搜索下一个(包括next_fd)为0的位,也是分配一个文教描述符  /*   * N.B. For clone tasks sharing a files structure, this test   * will limit the total number of files that can be opened.   */  if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//检查是否超过当前进程限定的大可打开文件数   goto out;

 /* Do we need to expand the fd array or fd set?  */  error = expand_files(files, fd);//根据需要扩展fd,稍后我们会详细介绍该函数。返回值<0,错误;返回值>0,扩展后再次进行fd的分配  if (error < 0)   goto out;

 if (error) {   /*     * If we needed to expand the fs array we    * might have blocked - try again.    */   error = -EMFILE;   goto repeat;//之前进行了扩展操作,重新进行一次空闲fd的分配  }

 FD_SET(fd, fdt->open_fds);//在open_fds的位图上置位  FD_CLR(fd, fdt->close_on_exec);  fdt->next_fd = fd + 1;//next_fd加1 #if 1  /* Sanity check */  if (fdt->fd[fd] != NULL) {   printk(KERN_WARNING "get_unused_fd: slot %d not NULL! ", fd);   fdt->fd[fd] = NULL;  } #endif  error = fd;

out:  spin_unlock(&files->file_lock);  return error; }  

  current->signal->rlim[RLIMIT_NOFILE].rlim_cur是一个进程可以打开的大文件数量。我们首先来看RLIMIT_NOFILE,该值定义如下:

# define RLIMIT_NOFILE  7 /* max number of open files */

  在signal结构中,rlim是struct rlimit类型的数组,

struct signal_struct {  ...  struct rlimit rlim[RLIM_NLIMITS];  ... };

  struct rlimit定义如下

struct rlimit {  unsigned long rlim_cur;//当前值  unsigned long rlim_max;//大值

  这些值时是在哪设定的呢?我们应该知道,linux内核通过fork创建进程,第一个进程是静态定义的。因此,如果进程创建后没有修改这些值,那么这些和第一个进程中的值应该是一样的。下面是第一个进程的task_struct结构,仅列出部分数据。

linux/arch/arm/kernel/init_task.c

struct task_struct init_task = INIT_TASK(init_task);

#define INIT_TASK(tsk) {          ...  .signal  = &init_signals,     ...   }  

  init_signals的定义如下:

#define INIT_SIGNALS(sig) {  .count  = ATOMIC_INIT(1),    .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),  .shared_pending = {       .list = LIST_HEAD_INIT(sig.shared_pending.list),   .signal =  {{0}}},  .posix_timers  = LIST_HEAD_INIT(sig.posix_timers),   .cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers),   .rlim  = INIT_RLIMITS,     }

includeasm-genericesource.h #define INIT_RLIMITS       {          [RLIMIT_CPU]  = {  RLIM_INFINITY,  RLIM_INFINITY },  [RLIMIT_FSIZE]  = {  RLIM_INFINITY,  RLIM_INFINITY },  [RLIMIT_DATA]  = {  RLIM_INFINITY,  RLIM_INFINITY },  [RLIMIT_STACK]  = {       _STK_LIM,   _STK_LIM_MAX },  [RLIMIT_CORE]  = {              0,  RLIM_INFINITY },  [RLIMIT_RSS]  = {  RLIM_INFINITY,  RLIM_INFINITY },  [RLIMIT_NPROC]  = {              0,              0 },  [RLIMIT_NOFILE]  = {       INR_OPEN,       INR_OPEN },  [RLIMIT_MEMLOCK] = {    MLOCK_LIMIT,    MLOCK_LIMIT },  [RLIMIT_AS]  = {  RLIM_INFINITY,  RLIM_INFINITY },  [RLIMIT_LOCKS]  = {  RLIM_INFINITY,  RLIM_INFINITY },  [RLIMIT_SIGPENDING] = {   0,        0 },  [RLIMIT_MSGQUEUE] = {   MQ_BYTES_MAX,   MQ_BYTES_MAX },  [RLIMIT_NICE]  = { 0, 0 },     [RLIMIT_RTPRIO]  = { 0, 0 },    }

#define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */ #define INR_OPEN 1024  /* Initial setting for nfile rlimits */  

  从上面的代码我们可以看到rlim_cur = 1024,也是说进程多可以打开1024个文件。



get Linux 文件描述符 fd

需要 登录 后方可回复, 如果你还没有账号请 注册新账号