linux内核中的文件描述符(四)--fd的分配--get_unused_fdKernelversion:2.6.14CPUarchitecture:ARM920920TAuthor:ce123()在linux内核中主要有两个函数涉及到文件描述符的分配:get_unused_fd和locate_fd。本文主要讲解l
linux内核中的文件描述符(四)--fd的分配--get_unused_fd
Kernelversion:2.6.14
CPUarchitecture:ARM920T
Author:ce123()
在linux内核中主要有两个函数涉及到文件描述符的分配:get_unused_fd和locate_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,扩展后再次进行fd的分配 if (error 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是structrlimit类型的字段linux 文件描述符,
struct signal_struct { ... struct rlimit rlim[RLIM_NLIMITS]; ... };
structrlimit定义如下
struct rlimit { unsigned long rlim_cur;//当前值 unsigned long rlim_max;//最大值 };
这种值时是在哪设定的呢?我们应当晓得,linux内核通过fork创建进程,第一个进程是静态定义的。为此linux 文件描述符,假如进程创建后没有更改那些值linux多线程,这么那些和第一个进程中的值应当是一样的。下边是第一个进程的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, } includeasm-genericresource.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硬盘安装linux,也就是说进程最多可以打开1024个文件。