作者:gfree.wind@gmail.com
博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
======================================================================================================
继续昨天的学习。
昨天学习alloc_fd时,还有一个函数expand_files没有进入跟踪。
- int expand_files(struct files_struct *files, int nr)
- {
- struct fdtable *fdt;
-
- fdt = files_fdtable(files);
-
- /*
- * N.B. For clone tasks sharing a files structure, this test
- * will limit the total number of files that can be opened.
- */
- /* 检查是否超过当前进程限定的最大可打开文件数 */
- if (nr >= rlimit(RLIMIT_NOFILE))
- return -EMFILE;
-
- /* Do we need to expand? */
- /*
- 如果nr小于max_fds,即目前的文件表的个数已经超过了nr, 所以无需扩展。
- 这也说明,文件表只会增大,不会减小。
- */
- if (nr fdt->max_fds)
- return 0;
-
- /* Can we expand? */
- /*
- 检查是否超过了系统限定的最大可打开文件数
- 注意前面的检查为当前进程的打开文件数,此处的检查为系统可打开的文件数——所有进程
- */
- if (nr >= sysctl_nr_open)
- return -EMFILE;
-
- /* All good, so we try */
- /* 真正去做expand*/
- return expand_fdtable(files, nr);
- }
进入expand_fdtable
- static int expand_fdtable(struct files_struct *files, int nr)
- __releases(files->file_lock)
- __acquires(files->file_lock)
- {
- struct fdtable *new_fdt, *cur_fdt;
-
- spin_unlock(&files->file_lock);
- /* 申请新的文件表 */
- new_fdt = alloc_fdtable(nr);
- spin_lock(&files->file_lock);
- if (!new_fdt)
- return -ENOMEM;
- /*
- * extremely unlikely race - sysctl_nr_open decreased between the check in
- * caller and alloc_fdtable(). Cheaper to catch it here...
- */
- /* 如注释所示,由于竞争,有可能在申请nr个数的新文件表时,修改了sysctl_nr_open,导致新的文件表个数 小于我们所需要的。所以,这里需要对new_fdt->max_fds和nr进行判断。如果小于nr,那么expand失败 */
- if (unlikely(new_fdt->max_fds = nr)) {
- __free_fdtable(new_fdt);
- return -EMFILE;
- }
- /*
- * Check again since another task may have expanded the fd table while
- * we dropped the lock
- */
- cur_fdt = files_fdtable(files);
- /* 如注释所示,有可能另外一个进程已经扩展了文件表,所以这里再次判断 */
- if (nr >= cur_fdt->max_fds) {
- /* 复制文件表 */
- /* Continue as planned */
- copy_fdtable(new_fdt, cur_fdt);
- rcu_assign_pointer(files->fdt, new_fdt);
- /*
- 对于文件表结构struct files_struct,其成员变量fd_array为一个大小为NR_OPEN_DEFAULT的数 组。这是一种常用的技巧。一般来说,进程的打开的文件不会太多,所以可以直接使用一个比较小的数组,这 样可以提高效率避免二次分配,同时由于数组较小,并不会太浪费空间。当文件个数超过数组大小的时候,再 重新申请内存。*/
- if (cur_fdt->max_fds > NR_OPEN_DEFAULT)
- free_fdtable(cur_fdt);
- } else {
- /* Somebody else expanded, so undo our attempt */
- __free_fdtable(new_fdt);
- }
- return 1;
- }
expand_files结束之后,alloc_fd也学习完了,即宏get_unused_fd_flags也就结束了,那么我们就再次回到了函数sock_alloc_file,继续学习其调用的其它函数。