linux内核中的文件描述符 四 --fd的分配--get unused fd

本文详细解析了Linux内核中get_unused_fd函数的工作原理,该函数用于在进程的文件描述符表中查找并分配一个未使用的文件描述符。文章深入介绍了文件描述符位图、RLIMIT_NOFILE限制及fd的分配流程。
               

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

Kernel version:2.6.14

CPU architecture:ARM920T

Author:ce123(http://blog.youkuaiyun.com/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.cstruct 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个文件。

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值