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 plaincopy
print?
- staticintlocate_fd(structfiles_struct*files,
- structfile*file,unsignedintorig_start)//从orig_start位开端分配fd
- {
- unsignedintnewfd;
- unsignedintstart;
- interror;
- structfdtable*fdt;
- error=-EINVAL;
- if(orig_start>=current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//查看orig_start是大于进程最大能够翻开文件的数量
- gotoout;
- repeat:
- fdt=files_fdtable(files);//文件描述符位图
- /*
- *Someonemighthaveclosedfdsintherange
- *orig_start..fdt->next_fd
- */
- start=orig_start;
- if(start
next_fd) - start=fdt->next_fd;//假如orig_start小于next_fd,那就从next_fd开端分配
- newfd=start;
- if(start
max_fdset){//max_fdset是描述符问题的位数,下面会具体解说 - newfd=find_next_zero_bit(fdt->open_fds->fds_bits,
- fdt->max_fdset,start);//分配fd
- }
- error=-EMFILE;
- if(newfd>=current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//进行判别,分配的fd不能大于进程最大能够翻开的文件数量
- gotoout;
- error=expand_files(files,newfd);//文件描述符表的扩展,这个咱们留在下一篇文章中具体解说
- if(error<0)
- gotoout;
- /*
- *Ifweneededtoexpandthefsarraywe
- *mighthaveblocked-tryagain.
- */
- if(error)
- gotorepeat;
- /*
- *Wereacquiredfiles_lock,sowearesafeaslongas
- *wereacquirethefdtablepointeranduseitwhileholding
- *thelock,noonecanfreeitduringthattime.
- */
- fdt=files_fdtable(files);
- if(start<=fdt->next_fd)
- fdt->next_fd=newfd+1;//更新next_fd值
- error=newfd;
- out:
- returnerror;
- }
max_fdset值的剖析和rlim_cur差不多,开始的值时从父进程承继过来的。
[plain]view plaincopy
print?
- linux/arch/arm/kernel/init_task.c
- structtask_structinit_task=INIT_TASK(init_task);
- #defineINIT_TASK(tsk)\
- {\
- …
- .files=&init_files,\
- …
- }
init_files的界说如下:
[plain]view plaincopy
print?
- staticstructfiles_structinit_files=INIT_FILES;
- linux/init_task.h
- #defineINIT_FDTABLE\
- {\
- .max_fds=NR_OPEN_DEFAULT,\
- .max_fdset=__FD_SETSIZE,\
- .next_fd=0,\
- .fd=&init_files.fd_array[0],\
- .close_on_exec=&init_files.close_on_exec_init,\
- .open_fds=&init_files.open_fds_init,\
- .rcu=RCU_HEAD_INIT,\
- .free_files=NULL,\
- .next=NULL,\
- }
- #defineNR_OPEN_DEFAULTBITS_PER_LONG
- #define__FD_SETSIZE1024
- #defineINIT_FILES\
- {\
- .count=ATOMIC_INIT(1),\
- .file_lock=SPIN_LOCK_UNLOCKED,\
- .fdt=&init_files.fdtab,\
- .fdtab=INIT_FDTABLE,\
- .close_on_exec_init={{0,}},\
- .open_fds_init={{0,}},\
- .fd_array={NULL,}\
- }
BITS_PER_LONG是long型数据的字节数,即4*8=3,也就是说max_fds = 32。max_fdset为1024。max_fdset是进程翻开文件描述符位图open_fds的巨细。open_fds是fd_set的指针。
[plain]view plaincopy
print?
- typedef__kernel_fd_setfd_set;
- #undef__NFDBITS
- #define__NFDBITS(8*sizeof(unsignedlong))
- #undef__FD_SETSIZE
- #define__FD_SETSIZE1024
- #undef__FDSET_LONGS
- #define__FDSET_LONGS(__FD_SETSIZE/__NFDBITS)
- #undef__FDELT
- #define__FDELT(d)((d)/__NFDBITS)
- #undef__FDMASK
- #define__FDMASK(d)(1UL<<((d)%__NFDBITS))
- typedefstruct{
- unsignedlongfds_bits[__FDSET_LONGS];
- }__kernel_fd_set;
fds_bits是一个long型数组,共有32个元素,共有1024bit。