linux內核中的文件描述符(四)--fd的分配--get_unused_fd
CPU architecture:ARM920T
本文引用地址:http://m.butianyuan.cn/article/201611/320000.htmAuthor:ce123(http://blog.csdn.net/ce123)
在linux內核中主要有兩個函數涉及到文件描述符的分配:get_unused_fd和locate_fd。本文主要講解get_unused_fd,將會在下一篇文章中介紹locate_fd。首先給出get_unused_fd的定義(fs/open.c):
[plain]view plaincopyprint?
- intget_unused_fd(void)
- {
- structfiles_struct*files=current->files;//獲得當前進程的打開文件列表files
- intfd,error;
- structfdtable*fdt;
- error=-EMFILE;
- spin_lock(&files->file_lock);
- repeat:
- fdt=files_fdtable(files);//獲得文件描述符位圖結構
- fd=find_next_zero_bit(fdt->open_fds->fds_bits,
- fdt->max_fdset,
- fdt->next_fd);
- //find_next_zero_bit函數在文件描述符位圖fds_bits中從next_fd位開始搜索下一個(包括next_fd)為0的位,也就是分配一個文教描述符
- /*
- *N.B.Forclonetaskssharingafilesstructure,thistest
- *willlimitthetotalnumberoffilesthatcanbeopened.
- */
- if(fd>=current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//檢查是否超過當前進程限定的最大可打開文件數
- gotoout;
- /*Doweneedtoexpandthefdarrayorfdset?*/
- error=expand_files(files,fd);//根據需要擴展fd,稍后我們會詳細介紹該函數。返回值<0,錯誤;返回值>0,擴展后再次進行fd的分配
- if(error<0)
- gotoout;
- if(error){
- /*
- *Ifweneededtoexpandthefsarraywe
- *mighthaveblocked-tryagain.
- */
- error=-EMFILE;
- gotorepeat;//之前進行了擴展操作,重新進行一次空閑fd的分配
- }
- FD_SET(fd,fdt->open_fds);//在open_fds的位圖上置位
- FD_CLR(fd,fdt->close_on_exec);
- fdt->next_fd=fd+1;//next_fd加1
- #if1
- /*Sanitycheck*/
- if(fdt->fd[fd]!=NULL){
- printk(KERN_WARNING"get_unused_fd:slot%dnotNULL!n",fd);
- fdt->fd[fd]=NULL;
- }
- #endif
- error=fd;
- out:
- spin_unlock(&files->file_lock);
- returnerror;
- }
current->signal->rlim[RLIMIT_NOFILE].rlim_cur是一個進程可以打開的最大文件數量。我們首先來看RLIMIT_NOFILE,該值定義如下:
[plain]view plaincopyprint?
- #defineRLIMIT_NOFILE7/*maxnumberofopenfiles*/
在signal結構中,rlim是struct rlimit類型的數組,
[plain]view plaincopyprint?
- structsignal_struct{
- ...
- structrlimitrlim[RLIM_NLIMITS];
- ...
- };
[plain]view plaincopyprint?
- structrlimit{
- unsignedlongrlim_cur;//當前值
- unsignedlongrlim_max;//最大值
- };
這些值時是在哪設定的呢?我們應該知道,linux內核通過fork創(chuàng)建進程,第一個進程是靜態(tài)定義的。因此,如果進程創(chuàng)建后沒有修改這些值,那么這些和第一個進程中的值應該是一樣的。下面是第一個進程的task_struct結構,僅列出部分數據。
[plain]view plaincopyprint?
- linux/arch/arm/kernel/init_task.c
- structtask_structinit_task=INIT_TASK(init_task);
- #defineINIT_TASK(tsk)
- {
- ...
- .signal=&init_signals,
- ...
- }
[plain]view plaincopyprint?
- #defineINIT_SIGNALS(sig){
- .count=ATOMIC_INIT(1),
- .wait_chldexit=__WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),
- .shared_pending={
- .list=LIST_HEAD_INIT(sig.shared_pending.list),
- .signal={{0}}},
- .posix_timers=LIST_HEAD_INIT(sig.posix_timers),
- .cpu_timers=INIT_CPU_TIMERS(sig.cpu_timers),
- .rlim=INIT_RLIMITS,
- }
- includeasm-genericresource.h
- #defineINIT_RLIMITS
- {
- [RLIMIT_CPU]={RLIM_INFINITY,RLIM_INFINITY},
- [RLIMIT_FSIZE]={RLIM_INFINITY,RLIM_INFINITY},
- [RLIMIT_DATA]={RLIM_INFINITY,RLIM_INFINITY},
- [RLIMIT_STACK]={_STK_LIM,_STK_LIM_MAX},
- [RLIMIT_CORE]={0,RLIM_INFINITY},
- [RLIMIT_RSS]={RLIM_INFINITY,RLIM_INFINITY},
- [RLIMIT_NPROC]={0,0},
- [RLIMIT_NOFILE]={INR_OPEN,INR_OPEN},
- [RLIMIT_MEMLOCK]={MLOCK_LIMIT,MLOCK_LIMIT},
- [RLIMIT_AS]={RLIM_INFINITY,RLIM_INFINITY},
- [RLIMIT_LOCKS]={RLIM_INFINITY,RLIM_INFINITY},
- [RLIMIT_SIGPENDING]={0,0},
- [RLIMIT_MSGQUEUE]={MQ_BYTES_MAX,MQ_BYTES_MAX},
- [RLIMIT_NICE]={0,0},
- [RLIMIT_RTPRIO]={0,0},
- }
- #defineNR_OPEN(1024*1024)/*Absoluteupperlimitonfdnum*/
- #defineINR_OPEN1024/*Initialsettingfornfilerlimits*/
評論