天天看點

TCP/IP源碼學習(48)——socket與VFS的關聯(2)

作者:[email protected]

部落格:blog.focus-linux.net   linuxfocus.blog.chinaunix.net 

本文的copyleft歸[email protected]所有,使用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)

    /* 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);

    }

     * 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 */

    return 1;

expand_files結束之後,alloc_fd也學習完了,即宏get_unused_fd_flags也就結束了,那麼我們就再次回到了函數sock_alloc_file,繼續學習其調用的其它函數。

繼續閱讀