linux内核中的文件描述符(四)--fd的分配--get_unused_fd

长平狐 发布于 2013/06/03 14:52
阅读 148
收藏 0

linux内核中的文件描述符(四)--fd的分配--get_unused_fd

Kernel version:2.6.14

CPU architecture:ARM920T

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

在linux内核中主要有两个函数涉及到文件描述符的分配:get_unused_fd和locate_fd。本文主要讲解get_unused_fd,将会在下一篇文章中介绍locate_fd。首先给出get_unused_fd的定义(fs/open.c):

int get_unused_fd(void)
{
	struct files_struct * files = current->files;//获得当前进程的打开文件列表files
	int fd, error;
	struct fdtable *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. For clone tasks sharing a files structure, this test
	 * will limit the total number of files that can be opened.
	 */
	if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)//检查是否超过当前进程限定的最大可打开文件数
		goto out;

	/* Do we need to expand the fd array or fd set?  */
	error = expand_files(files, fd);//根据需要扩展fd,稍后我们会详细介绍该函数。返回值<0,错误;返回值>0,扩展后再次进行fd的分配
	if (error < 0)
		goto out;

	if (error) {
		/*
	 	 * If we needed to expand the fs array we
		 * might have blocked - try again.
		 */
		error = -EMFILE;
		goto repeat;//之前进行了扩展操作,重新进行一次空闲fd的分配
	}

	FD_SET(fd, fdt->open_fds);//在open_fds的位图上置位
	FD_CLR(fd, fdt->close_on_exec);
	fdt->next_fd = fd + 1;//next_fd加1
#if 1
	/* Sanity check */
	if (fdt->fd[fd] != NULL) {
		printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
		fdt->fd[fd] = NULL;
	}
#endif
	error = fd;

out:
	spin_unlock(&files->file_lock);
	return error;
}

current->signal->rlim[RLIMIT_NOFILE].rlim_cur是一个进程可以打开的最大文件数量。我们首先来看RLIMIT_NOFILE,该值定义如下:

# define RLIMIT_NOFILE		7	/* max number of open files */

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

struct signal_struct {
	...
	struct rlimit rlim[RLIM_NLIMITS];
	...	
};
struct rlimit定义如下
struct rlimit {
	unsigned long	rlim_cur;//当前值
	unsigned long	rlim_max;//最大值
};

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

linux/arch/arm/kernel/init_task.c

struct task_struct init_task = INIT_TASK(init_task);

#define INIT_TASK(tsk)	\
{									\
	...
	.signal		= &init_signals,				\
	...			
}
init_signals的定义如下:

#define INIT_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
#define INIT_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 },				\
}

#define NR_OPEN (1024*1024)	/* Absolute upper limit on fd num */
#define INR_OPEN 1024		/* Initial setting for nfile rlimits */
从上面的代码我们可以看到rlim_cur = 1024,也就是说进程最多可以打开1024个文件。


原文链接:http://blog.csdn.net/ce123/article/details/8487559
加载中
返回顶部
顶部