×
单片机 > 单片机程序设计 > 详情

linux内核中的文件描述符(四)--fd的分配--get_unused_fd

发布时间:2020-08-31 发布时间:
|
Kernel version:2.6.14

CPU architecture:ARM920T

Author:ce123(http://blog.csdn.net/ce123)

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

 

[plain] view plain copy
 
 print?
  1. int get_unused_fd(void)  
  2. {  
  3.     struct files_struct * files = current->files;//获得当前进程的打开文件列表files  
  4.     int fd, error;  
  5.     struct fdtable *fdt;  
  6.   
  7.     error = -EMFILE;  
  8.     spin_lock(&files->file_lock);  
  9.   
  10. repeat:  
  11.     fdt = files_fdtable(files);//获得文件描述符位图结构  
  12.     fd = find_next_zero_bit(fdt->open_fds->fds_bits,  
  13.                 fdt->max_fdset,  
  14.                 fdt->next_fd);  
  15. //find_next_zero_bit函数在文件描述符位图fds_bits中从next_fd位开始搜索下一个(包括next_fd)为0的位,也就是分配一个文教描述符  
  16.     /*  
  17.      * N.B. For clone tasks sharing a files structure, this test  
  18.      * will limit the total number of files that can be opened.  
  19.      */  
  20.     if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//检查是否超过当前进程限定的最大可打开文件数  
  21.         goto out;  
  22.   
  23.     /* Do we need to expand the fd array or fd set?  */  
  24.     error = expand_files(files, fd);//根据需要扩展fd,稍后我们会详细介绍该函数。返回值<0,错误;返回值>0,扩展后再次进行fd的分配  
  25.     if (error 
  26.         goto out;  
  27.   
  28.     if (error) {  
  29.         /*  
  30.          * If we needed to expand the fs array we  
  31.          * might have blocked - try again.  
  32.          */  
  33.         error = -EMFILE;  
  34.         goto repeat;//之前进行了扩展操作,重新进行一次空闲fd的分配  
  35.     }  
  36.   
  37.     FD_SET(fd, fdt->open_fds);//在open_fds的位图上置位  
  38.     FD_CLR(fd, fdt->close_on_exec);  
  39.     fdt->next_fd = fd + 1;//next_fd加1  
  40. #if 1  
  41.     /* Sanity check */  
  42.     if (fdt->fd[fd] != NULL) {  
  43.         printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);  
  44.         fdt->fd[fd] = NULL;  
  45.     }  
  46. #endif  
  47.     error = fd;  
  48.   
  49. out:  
  50.     spin_unlock(&files->file_lock);  
  51.     return error;  
  52. }  

 

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

 

[plain] view plain copy
 
 print?
  1. # define RLIMIT_NOFILE      7   /* max number of open files */  

 

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

 

[plain] view plain copy
 
 print?
  1. struct signal_struct {  
  2.     ...  
  3.     struct rlimit rlim[RLIM_NLIMITS];  
  4.     ...   
  5. };  
struct rlimit定义如下
[plain] view plain copy
 
 print?
  1. struct rlimit {  
  2.     unsigned long   rlim_cur;//当前值  
  3.     unsigned long   rlim_max;//最大值  
  4. };  

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

 

[plain] view plain copy
 
 print?
  1. linux/arch/arm/kernel/init_task.c  
  2.   
  3. struct task_struct init_task = INIT_TASK(init_task);  
  4.   
  5. #define INIT_TASK(tsk)  \  
  6. {                                   \  
  7.     ...  
  8.     .signal     = &init_signals,                \  
  9.     ...           
  10. }  
init_signals的定义如下:

 

 

 

[plain] view plain copy
 
 print?
  1. #define INIT_SIGNALS(sig) { \  
  2.     .count      = ATOMIC_INIT(1),       \  
  3.     .wait_chldexit  = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\  
  4.     .shared_pending = {                 \  
  5.         .list = LIST_HEAD_INIT(sig.shared_pending.list),    \  
  6.         .signal =  {{0}}}, \  
  7.     .posix_timers    = LIST_HEAD_INIT(sig.posix_timers),        \  
  8.     .cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers),      \  
  9.     .rlim       = INIT_RLIMITS,                 \  
  10. }  
  11.   
  12. include\asm-generic\resource.h  
  13. #define INIT_RLIMITS                            \  
  14. {                                   \  
  15.     [RLIMIT_CPU]        = {  RLIM_INFINITY,  RLIM_INFINITY },   \  
  16.     [RLIMIT_FSIZE]      = {  RLIM_INFINITY,  RLIM_INFINITY },   \  
  17.     [RLIMIT_DATA]       = {  RLIM_INFINITY,  RLIM_INFINITY },   \  
  18.     [RLIMIT_STACK]      = {       _STK_LIM,   _STK_LIM_MAX },   \  
  19.     [RLIMIT_CORE]       = {              0,  RLIM_INFINITY },   \  
  20.     [RLIMIT_RSS]        = {  RLIM_INFINITY,  RLIM_INFINITY },   \  
  21.     [RLIMIT_NPROC]      = {              0,              0 },   \  
  22.     [RLIMIT_NOFILE]     = {       INR_OPEN,       INR_OPEN },   \  
  23.     [RLIMIT_MEMLOCK]    = {    MLOCK_LIMIT,    MLOCK_LIMIT },   \  
  24.     [RLIMIT_AS]     = {  RLIM_INFINITY,  RLIM_INFINITY },   \  
  25.     [RLIMIT_LOCKS]      = {  RLIM_INFINITY,  RLIM_INFINITY },   \  
  26.     [RLIMIT_SIGPENDING] = {         0,         0 }, \  
  27.     [RLIMIT_MSGQUEUE]   = {   MQ_BYTES_MAX,   MQ_BYTES_MAX },   \  
  28.     [RLIMIT_NICE]       = { 0, 0 },             \  
  29.     [RLIMIT_RTPRIO]     = { 0, 0 },             \  
  30. }  
  31.   
  32. #define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */  
  33. #define INR_OPEN 1024       /* Initial setting for nfile rlimits */  
从上面的代码我们可以看到rlim_cur = 1024,也就是说进程最多可以打开1024个文件。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向