linux內(nèi)核中的文件描述符(六)--fd的分配--expand_files
CPU architecture:ARM920T
本文引用地址:http://m.butianyuan.cn/article/201611/320002.htmAuthor:ce123(http://blog.csdn.net/ce123)
我們先貼出expand_files函數(shù)的源碼:
[plain]view plaincopyprint?
- intexpand_files(structfiles_struct*files,intnr)
- {
- interr,expand=0;
- structfdtable*fdt;
- fdt=files_fdtable(files);
- if(nr>=fdt->max_fdset||nr>=fdt->max_fds){//我們?cè)谇懊娴奈恼轮幸呀?jīng)分析過(guò),初始時(shí)max_fdset=1024,max_fds=32
- if(fdt->max_fdset>=NR_OPEN||//#defineNR_OPEN(1024*1024)/*Absoluteupperlimitonfdnum*/
- fdt->max_fds>=NR_OPEN||nr>=NR_OPEN){
- err=-EMFILE;//max_fdset和max_fds都不能大于NR_OPEN,否則返回-EMFILE,即打開太多的文件
- gotoout;
- }
- expand=1;
- if((err=expand_fdtable(files,nr)))//真正進(jìn)行擴(kuò)展
- gotoout;
- }
- err=expand;
- out:
- returnerr;
- }
expand_files函數(shù)進(jìn)行一些檢查后調(diào)用expand_fdtable進(jìn)行文件描述符表的擴(kuò)展,下面分析expand_fdtable函數(shù)。
[plain]view plaincopyprint?
- staticintexpand_fdtable(structfiles_struct*files,intnr)
- __releases(files->file_lock)
- __acquires(files->file_lock)
- {
- interror=0;
- structfdtable*fdt;
- structfdtable*nfdt=NULL;
- spin_unlock(&files->file_lock);
- nfdt=alloc_fdtable(nr);//根據(jù)nr重新創(chuàng)建一個(gè)新的fdtable
- if(!nfdt){
- error=-ENOMEM;
- spin_lock(&files->file_lock);
- gotoout;
- }
- spin_lock(&files->file_lock);
- fdt=files_fdtable(files);
- /*
- *Checkagainsinceanothertaskmayhaveexpandedthe
- *fdtablewhilewedroppedthelock
- */
- if(nr>=fdt->max_fds||nr>=fdt->max_fdset){//nr值必須大于max_fds和max_fdset值,這里再次進(jìn)行檢查是防止另一個(gè)進(jìn)程進(jìn)行了expand
- copy_fdtable(nfdt,fdt);//將舊的fdtable中的內(nèi)容拷貝至新的fdtable
- }else{
- /*Somebodyexpandedwhilewedroppedfile_lock*/
- spin_unlock(&files->file_lock);
- __free_fdtable(nfdt);
- spin_lock(&files->file_lock);
- gotoout;
- }
- rcu_assign_pointer(files->fdt,nfdt);//用新的fdtable替換舊的fdtable
- free_fdtable(fdt);//釋放舊的fdtable
- out:
- returnerror;
- }
[plain]view plaincopyprint?
- staticstructfdtable*alloc_fdtable(intnr)
- {
- structfdtable*fdt=NULL;
- intnfds=0;
- fd_set*new_openset=NULL,*new_execset=NULL;
- structfile**new_fds;
- fdt=kmalloc(sizeof(*fdt),GFP_KERNEL);
- if(!fdt)
- gotoout;
- memset(fdt,0,sizeof(*fdt));
- nfds=__FD_SETSIZE;//#define__FD_SETSIZE1024
- //#definePAGE_SHIFT12
- //#definePAGE_SIZE(1UL<
- /*Expandtothemaxineasysteps*/
- do{
- if(nfds<(PAGE_SIZE*8))//dfds=1024
- nfds=PAGE_SIZE*8;
- else{
- nfds=nfds*2;
- if(nfds>NR_OPEN)
- nfds=NR_OPEN;
- }
- }while(nfds<=nr);//第一次expand時(shí),nr應(yīng)該等于32
- new_openset=alloc_fdset(nfds);//分配打開文件位圖
- new_execset=alloc_fdset(nfds);
- if(!new_openset||!new_execset)
- gotoout;
- fdt->open_fds=new_openset;
- fdt->close_on_exec=new_execset;
- fdt->max_fdset=nfds;//更新max_fdset值,此時(shí)這個(gè)值為32k
- nfds=NR_OPEN_DEFAULT;//nfds=32
- /*
- *Expandtothemaxineasysteps,andkeepexpandingituntil
- *wehaveenoughfortherequestedfdarraysize.
- */
- do{
- #ifNR_OPEN_DEFAULT<256
- if(nfds<256)
- nfds=256;//nfds=256(32->256->1024)
- //無(wú)法超過(guò)1024,因?yàn)樵谧铋_始的就進(jìn)行了檢查,一定要小于current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
- else
- #endif
- if(nfds<(PAGE_SIZE/sizeof(structfile*)))
- nfds=PAGE_SIZE/sizeof(structfile*);
- else{
- nfds=nfds*2;
- if(nfds>NR_OPEN)
- nfds=NR_OPEN;
- }
- }while(nfds<=nr);
- new_fds=alloc_fd_array(nfds);//分配文件描述符數(shù)組
- if(!new_fds)
- gotoout;
- fdt->fd=new_fds;
- fdt->max_fds=nfds;//更新max_fds
- fdt->free_files=NULL;
- returnfdt;
- out:
- if(new_openset)
- free_fdset(new_openset,nfds);
- if(new_execset)
- free_fdset(new_execset,nfds);
- kfree(fdt);
- returnNULL;
- }
評(píng)論