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

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

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

CPU architecture:ARM920T

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

继续上一篇博客的内容,分析另一个文件描述符fd的分配函数locate_fd。dup系统调用用于复制一个文件描述符对应的文件,返回值是个文件描述符。在前面的文章中,我们已经分析过了dup的源码(http://blog.csdn.net/ce123/article/details/8444482),在这里我们深入分析locate_fd函数,其定义如下:

 

[plain] view plain copy
 
 print?
  1. static int locate_fd(struct files_struct *files,   
  2.                 struct file *file, unsigned int orig_start)//从orig_start位开始分配fd  
  3. {  
  4.     unsigned int newfd;  
  5.     unsigned int start;  
  6.     int error;  
  7.     struct fdtable *fdt;  
  8.   
  9.     error = -EINVAL;  
  10.     if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//检查orig_start是大于进程最大可以打开文件的数量  
  11.         goto out;  
  12.   
  13. repeat:  
  14.     fdt = files_fdtable(files);//文件描述符位图  
  15.     /*  
  16.      * Someone might have closed fd's in the range  
  17.      * orig_start..fdt->next_fd  
  18.      */  
  19.     start = orig_start;  
  20.     if (start next_fd)  
  21.         start = fdt->next_fd;//如果orig_start小于next_fd,那就从next_fd开始分配  
  22.   
  23.     newfd = start;  
  24.     if (start max_fdset) {//max_fdset是描述符问题的位数,下面会具体讲解  
  25.         newfd = find_next_zero_bit(fdt->open_fds->fds_bits,  
  26.             fdt->max_fdset, start);//分配fd  
  27.     }  
  28.       
  29.     error = -EMFILE;  
  30.     if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//进行判断,分配的fd不能大于进程最大可以打开的文件数量  
  31.         goto out;  
  32.   
  33.     error = expand_files(files, newfd);//文件描述符表的扩展,这个我们留在下一篇文章中详细讲解  
  34.     if (error 
  35.         goto out;  
  36.   
  37.     /*  
  38.      * If we needed to expand the fs array we  
  39.      * might have blocked - try again.  
  40.      */  
  41.     if (error)  
  42.         goto repeat;  
  43.   
  44.     /*  
  45.      * We reacquired files_lock, so we are safe as long as  
  46.      * we reacquire the fdtable pointer and use it while holding  
  47.      * the lock, no one can free it during that time.  
  48.      */  
  49.     fdt = files_fdtable(files);  
  50.     if (start <= fdt->next_fd)  
  51.         fdt->next_fd = newfd + 1;//更新next_fd值  
  52.   
  53.     error = newfd;  
  54.       
  55. out:  
  56.     return error;  
  57. }  
max_fdset值的分析和rlim_cur差不多,最初的值时从父进程继承过来的。

 

 

[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.     .files      = &init_files,                  \  
  9.     ...           
  10. }  
init_files的定义如下:

 

 

[plain] view plain copy
 
 print?
  1. static struct files_struct init_files = INIT_FILES;  
  2.   
  3. linux/init_task.h  
  4.   
  5. #define INIT_FDTABLE \  
  6. {                           \  
  7.     .max_fds    = NR_OPEN_DEFAULT,      \  
  8.     .max_fdset  = __FD_SETSIZE,         \  
  9.     .next_fd    = 0,                \  
  10.     .fd     = &init_files.fd_array[0],  \  
  11.     .close_on_exec  = &init_files.close_on_exec_init, \  
  12.     .open_fds   = &init_files.open_fds_init,    \  
  13.     .rcu        = RCU_HEAD_INIT,        \  
  14.     .free_files = NULL,             \  
  15.     .next       = NULL,             \  
  16. }  
  17.   
  18. #define NR_OPEN_DEFAULT BITS_PER_LONG  
  19. #define __FD_SETSIZE    1024  
  20.   
  21. #define INIT_FILES \  
  22. {                           \  
  23.     .count      = ATOMIC_INIT(1),       \  
  24.     .file_lock  = SPIN_LOCK_UNLOCKED,       \  
  25.     .fdt        = &init_files.fdtab,        \  
  26.     .fdtab      = INIT_FDTABLE,         \  
  27.     .close_on_exec_init = { { 0, } },       \  
  28.     .open_fds_init  = { { 0, } },           \  
  29.     .fd_array   = { NULL, }             \  
  30. }  
BITS_PER_LONG是long型数据的字节数,即4*8=3,也就是说max_fds = 32。max_fdset为1024。max_fdset是进程打开文件描述符位图open_fds的大小。open_fds是fd_set的指针。

 

 

[plain] view plain copy
 
 print?
  1. typedef __kernel_fd_set     fd_set;  
  2.   
  3. #undef __NFDBITS  
  4. #define __NFDBITS   (8 * sizeof(unsigned long))  
  5.   
  6. #undef __FD_SETSIZE  
  7. #define __FD_SETSIZE    1024  
  8.   
  9. #undef __FDSET_LONGS  
  10. #define __FDSET_LONGS   (__FD_SETSIZE/__NFDBITS)  
  11.   
  12. #undef __FDELT  
  13. #define __FDELT(d)  ((d) / __NFDBITS)  
  14.   
  15. #undef __FDMASK  
  16. #define __FDMASK(d) (1UL <
  17.   
  18. typedef struct {  
  19.     unsigned long fds_bits [__FDSET_LONGS];  
  20. } __kernel_fd_set;  
fds_bits是一个long型数组,共有32个元素,共有1024bit。
关键字:linux内核  文件描述符  locate_fd 

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

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