新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > linux內(nèi)核中的文件描述符(六)--fd的分配--expand_files

        linux內(nèi)核中的文件描述符(六)--fd的分配--expand_files

        作者: 時(shí)間:2016-11-22 來(lái)源:網(wǎng)絡(luò) 收藏
        Kernel version:2.6.14

        CPU architecture:ARM920T

        本文引用地址:http://www.104case.com/article/201611/320002.htm

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

        我們先貼出expand_files函數(shù)的源碼:

        [plain]view plaincopy
        print?
        1. intexpand_files(structfiles_struct*files,intnr)
        2. {
        3. interr,expand=0;
        4. structfdtable*fdt;
        5. fdt=files_fdtable(files);
        6. if(nr>=fdt->max_fdset||nr>=fdt->max_fds){//我們?cè)谇懊娴奈恼轮幸呀?jīng)分析過(guò),初始時(shí)max_fdset=1024,max_fds=32
        7. if(fdt->max_fdset>=NR_OPEN||//#defineNR_OPEN(1024*1024)/*Absoluteupperlimitonfdnum*/
        8. fdt->max_fds>=NR_OPEN||nr>=NR_OPEN){
        9. err=-EMFILE;//max_fdset和max_fds都不能大于NR_OPEN,否則返回-EMFILE,即打開(kāi)太多的文件
        10. gotoout;
        11. }
        12. expand=1;
        13. if((err=expand_fdtable(files,nr)))//真正進(jìn)行擴(kuò)展
        14. gotoout;
        15. }
        16. err=expand;
        17. out:
        18. returnerr;
        19. }

        expand_files函數(shù)進(jìn)行一些檢查后調(diào)用expand_fdtable進(jìn)行文件描述符表的擴(kuò)展,下面分析expand_fdtable函數(shù)。

        [plain]view plaincopy
        print?
        1. staticintexpand_fdtable(structfiles_struct*files,intnr)
        2. __releases(files->file_lock)
        3. __acquires(files->file_lock)
        4. {
        5. interror=0;
        6. structfdtable*fdt;
        7. structfdtable*nfdt=NULL;
        8. spin_unlock(&files->file_lock);
        9. nfdt=alloc_fdtable(nr);//根據(jù)nr重新創(chuàng)建一個(gè)新的fdtable
        10. if(!nfdt){
        11. error=-ENOMEM;
        12. spin_lock(&files->file_lock);
        13. gotoout;
        14. }
        15. spin_lock(&files->file_lock);
        16. fdt=files_fdtable(files);
        17. /*
        18. *Checkagainsinceanothertaskmayhaveexpandedthe
        19. *fdtablewhilewedroppedthelock
        20. */
        21. if(nr>=fdt->max_fds||nr>=fdt->max_fdset){//nr值必須大于max_fds和max_fdset值,這里再次進(jìn)行檢查是防止另一個(gè)進(jìn)程進(jìn)行了expand
        22. copy_fdtable(nfdt,fdt);//將舊的fdtable中的內(nèi)容拷貝至新的fdtable
        23. }else{
        24. /*Somebodyexpandedwhilewedroppedfile_lock*/
        25. spin_unlock(&files->file_lock);
        26. __free_fdtable(nfdt);
        27. spin_lock(&files->file_lock);
        28. gotoout;
        29. }
        30. rcu_assign_pointer(files->fdt,nfdt);//用新的fdtable替換舊的fdtable
        31. free_fdtable(fdt);//釋放舊的fdtable
        32. out:
        33. returnerror;
        34. }
        我們?cè)賮?lái)看一下擴(kuò)展文件描述符表的關(guān)鍵函數(shù)alloc_fdtable,其定義如下:

        [plain]view plaincopy
        print?
        1. staticstructfdtable*alloc_fdtable(intnr)
        2. {
        3. structfdtable*fdt=NULL;
        4. intnfds=0;
        5. fd_set*new_openset=NULL,*new_execset=NULL;
        6. structfile**new_fds;
        7. fdt=kmalloc(sizeof(*fdt),GFP_KERNEL);
        8. if(!fdt)
        9. gotoout;
        10. memset(fdt,0,sizeof(*fdt));
        11. nfds=__FD_SETSIZE;//#define__FD_SETSIZE1024
        12.     //#definePAGE_SHIFT12
        13.     //#definePAGE_SIZE(1UL<
        14. /*Expandtothemaxineasysteps*/
        15. do{
        16. if(nfds<(PAGE_SIZE*8))//dfds=1024
        17. nfds=PAGE_SIZE*8;
        18. else{
        19. nfds=nfds*2;
        20. if(nfds>NR_OPEN)
        21. nfds=NR_OPEN;
        22. }
        23. }while(nfds<=nr);//第一次expand時(shí),nr應(yīng)該等于32
        24. new_openset=alloc_fdset(nfds);//分配打開(kāi)文件位圖
        25. new_execset=alloc_fdset(nfds);
        26. if(!new_openset||!new_execset)
        27. gotoout;
        28. fdt->open_fds=new_openset;
        29. fdt->close_on_exec=new_execset;
        30. fdt->max_fdset=nfds;//更新max_fdset值,此時(shí)這個(gè)值為32k
        31. nfds=NR_OPEN_DEFAULT;//nfds=32
        32. /*
        33. *Expandtothemaxineasysteps,andkeepexpandingituntil
        34. *wehaveenoughfortherequestedfdarraysize.
        35. */
        36. do{
        37. #ifNR_OPEN_DEFAULT<256
        38. if(nfds<256)
        39. nfds=256;//nfds=256(32->256->1024)
        40. //無(wú)法超過(guò)1024,因?yàn)樵谧铋_(kāi)始的就進(jìn)行了檢查,一定要小于current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
        41. else
        42. #endif
        43. if(nfds<(PAGE_SIZE/sizeof(structfile*)))
        44. nfds=PAGE_SIZE/sizeof(structfile*);
        45. else{
        46. nfds=nfds*2;
        47. if(nfds>NR_OPEN)
        48. nfds=NR_OPEN;
        49. }
        50. }while(nfds<=nr);
        51. new_fds=alloc_fd_array(nfds);//分配文件描述符數(shù)組
        52. if(!new_fds)
        53. gotoout;
        54. fdt->fd=new_fds;
        55. fdt->max_fds=nfds;//更新max_fds
        56. fdt->free_files=NULL;
        57. returnfdt;
        58. out:
        59. if(new_openset)
        60. free_fdset(new_openset,nfds);
        61. if(new_execset)
        62. free_fdset(new_execset,nfds);
        63. kfree(fdt);
        64. returnNULL;
        65. }
        alloc_fd_array和alloc_fdset采用kmalloc或者vmalloc進(jìn)行內(nèi)存分配。


        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 渝中区| 山阴县| 石首市| 霍城县| 肥乡县| 崇明县| 淮阳县| 镇康县| 阆中市| 赣州市| 井研县| 凉城县| 公安县| 加查县| 大同县| 逊克县| 社旗县| 清水县| 长宁区| 萍乡市| 靖西县| 安岳县| 门头沟区| 江山市| 桐梓县| 镇巴县| 哈巴河县| 调兵山市| 蓬莱市| 张家界市| 南江县| 诸城市| 镇江市| 准格尔旗| 吴忠市| 广东省| 盐源县| 怀远县| 西吉县| 白城市| 浦城县|