Linux内核判断fd类型,linux内核中的文件描述符(四)--fd的分配--get_unused_fd

Kernel version:2.6.14

CPU architecture:ARM920T本文引用地址:http://www.eepw.com.cn/article/201611/320000.htm

Author: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 plaincopy

print?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 plaincopy

print?#defineRLIMIT_NOFILE7/*maxnumberofopenfiles*/

在signal结构中,rlim是struct rlimit类型的数组,

[plain]view plaincopy

print?structsignal_struct{

...

structrlimitrlim[RLIM_NLIMITS];

...

};struct rlimit定义如下

[plain]view plaincopy

print?structrlimit{

unsignedlongrlim_cur;//当前值

unsignedlongrlim_max;//最大值

};

这些值时是在哪设定的呢?我们应该知道,linux内核通过fork创建进程,第一个进程是静态定义的。因此,如果进程创建后没有修改这些值,那么这些和第一个进程中的值应该是一样的。下面是第一个进程的task_struct结构,仅列出部分数据。

[plain]view plaincopy

print?linux/arch/arm/kernel/init_task.c

structtask_structinit_task=INIT_TASK(init_task);

#defineINIT_TASK(tsk)\

{\

...

.signal=&init_signals,\

...

}init_signals的定义如下:

[plain]view plaincopy

print?#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,\

}

include\asm-generic\resource.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*/从上面的代码我们可以看到rlim_cur = 1024,也就是说进程最多可以打开1024个文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值