返回顶部
首页 > 资讯 > 操作系统 >Linux系统下fd分配的方法是什么
  • 940
分享到

Linux系统下fd分配的方法是什么

2023-06-16 17:06:13 940人浏览 薄情痞子
摘要

这篇文章将为大家详细讲解有关linux系统下fd分配的方法是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。最近几天在公司里写网络通讯的代码比较多,自然就会涉及到io事件监测方法的问题。我

这篇文章将为大家详细讲解有关linux系统下fd分配的方法是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

最近几天在公司里写网络通讯的代码比较多,自然就会涉及到io事件监测方法的问题。我惊奇的发现select轮训的方法在那里居然还大行其道。我告诉他们现在无论在Linux系统下,还是windows系统下,select都应该被废弃不用了,其原因是在两个平台上select的系统调用都有一个可以说是致命的坑。

在windows上面单个fd_set中容纳的Socket handle个数不能超过FD_SETSIZE(在win32 winsock2.h里其定义为64,以VS2010版本为准),并且fd_set结构使用一个数组来容纳这些socket handle的,每次FD_SET宏都是向这个数组中放入一个socket handle,并且此过程中是限定了不能超过FD_SETSIZE,具体请自己查看winsock2.h中FD_SET宏的定义。

此处的问题是

若本身fd_set中的socket handle已经达到FD_SETSIZE个,那么后续的FD_SET操作实际上是没有效果的,对应socket handle的IO事件将被遗漏!!!

而在Linux系统下面,该问题其实也是处在fd_set的结构和FD_SET宏上。此时fd_set结构是使用bit位序列来记录每一个待检测IO事件的fd。记录的方式稍微复杂,如下

/usr/include/sys/select.h中

typedef long int __fd_mask;  #define __NFDBITS    (8 * sizeof (__fd_mask))  #define    __FDELT(d)    ((d) / __NFDBITS)   #define    __FDMASK(d)    ((__fd_mask) 1 << ((d) % __NFDBITS))   typedef struct    {        #ifdef __USE_XOPEN      __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];  # define __FDS_BITS(set) ((set)->fds_bits)  #else      __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];  # define __FDS_BITS(set) ((set)->__fds_bits)  #endif    } fd_set;   #define    FD_SET(fd, fdsetp)    __FD_SET (fd, fdsetp)

/usr/include/bits/select.h中

1 # define __FD_SET(d, set)    (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d))

可以看出,在上面的过程,实际上每个bit在fd_set的bit序列中的位置对应于fd的值。而fd_set结构中bit位个数是__FD_SETSIZE定义的,__FD_SETSIZE在/usr/include/bits/typesize.h(包含关系如下sys/socket.h -> bits/types.h -> bits/typesizes.h)中被定义为1024。

现在的问题是,当fd>=1024时,FD_SET宏实际上会引起内存写越界。而实际上在man select中对已也有明确的说明,如下

NOTES

An fd_set is a fixed size buffer. Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal to or
larger than FD_SETSIZE will result in undefined behavior. Moreover, POSIX requires fd to be a valid file descriptor.

这一点包括之前的我,是很多人没有注意到的,并且云风大神有篇博文《一起 select 引起的崩溃》也描述了这个问题。

可以看出在Linux系统select也是不安全的,若想使用,得小心翼翼的确认fd是否达到1024,但这很难做到,不然还是老老实实的用poll或epoll吧。

扯得有点远了,但也引出了本片文章要叙述的主题,就是Linux系统下fd值是怎么分配确定,大家都知道fd是int类型,但其值是怎么增长的,在下面的内容中我对此进行了一点分析,以2.6.30版本的kernel为例,欢迎拍砖。

首先得知道是哪个函数进行fd分配,对此我以pipe为例,它是分配fd的一个典型的syscall,在fs/pipe.c中定义了pipe和pipe2的syscall实现,如下

SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags)  {      int fd[2];      int error;       error = do_pipe_flags(fd, flags);      if (!error) {          if (copy_to_user(fildes, fd, sizeof(fd))) {              sys_close(fd[0]);              sys_close(fd[1]);              error = -EFAULT;          }      }      return error;  }   SYSCALL_DEFINE1(pipe, int __user *, fildes)  {      return sys_pipe2(fildes, 0);  }

进一步分析do_pipe_flags()实现,发现其使用get_unused_fd_flags(flags)来分配fd的,它是一个宏

#define get_unused_fd_flags(flags) alloc_fd(0, (flags)),位于include/linux/fs.h中

好了咱们找到了主角了,就是alloc_fd(),它就是内核章实际执行fd分配的函数。其位于fs/file.c,实现也很简单,如下

int alloc_fd(unsigned start, unsigned flags)  {      struct files_struct *files = current->files;      unsigned int fd;      int error;      struct fdtable *fdt;       spin_lock(&files->file_lock);  repeat:      fdt = files_fdtable(files);     fd = start;      if (fd < files->next_fd)          fd = files->next_fd;       if (fd < fdt->max_fds)          fd = find_next_zero_bit(fdt->open_fds->fds_bits,                         fdt->max_fds, fd);       error = expand_files(files, fd);      if (error < 0)          Goto out;             if (error)          goto repeat;       if (start <= files->next_fd)          files->next_fd = fd + 1;       FD_SET(fd, fdt->open_fds);      if (flags & O_CLOEXEC)          FD_SET(fd, fdt->close_on_exec);      else          FD_CLR(fd, fdt->close_on_exec);      error = fd;  #if 1            if (rcu_dereference(fdt->fd[fd]) != NULL) {          printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);          rcu_assign_pointer(fdt->fd[fd], NULL);      }  #endif   out:      spin_unlock(&files->file_lock);      return error;  }

在pipe的系统调用中start值始终为0,而中间比较关键的expand_files()函数是根据所给的fd值,判断是否需要对进程的打开文件表进行扩容,其函数头注释如下

此处对其实现就不做深究了,回到alloc_fd(),现在可以看出,其分配fd的原则是

每次优先分配fd值最小的空闲fd,当分配不成功,即返回EMFILE的错误码,这表示当前进程中fd太多。

到此也印证了在公司写的服务端程序(kernel是2.6.18)中,每次打印client链接对应的fd值得变化规律了,假如给一个新连接分配的fd值为8,那么其关闭之后,紧接着的新的链接分配到的fd也是8,再新的链接的fd值是逐渐加1的。

为此,我继续找了一下socket对应fd分配方法,发现最终也是 alloc_fd(0, (flags),调用序列如下
socket(sys_call) -> sock_map_fd() -> sock_alloc_fd() -> get_unused_fd_flags()
open系统调用也是用get_unused_fd_flags(),这里就不列举了。

现在想回头说说开篇的select的问题。由于Linux系统fd的分配规则,实际上是已经保证每次的fd值尽量的小,一般非IO频繁的系统,的确一个进程中fd值达到1024的概率比较小。因而对此到底是否该弃用select,还不能完全地做绝对的结论。如果设计的系统的确有其他措施保证fd值小于1024,那么用select无可厚非。

但在网络通讯程序这种场合是绝不应该作此假设的,所以还是尽量的不用select吧!!

关于Linux系统下fd分配的方法是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: Linux系统下fd分配的方法是什么

本文链接: https://lsjlt.com/news/284543.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Linux系统下fd分配的方法是什么
    这篇文章将为大家详细讲解有关Linux系统下fd分配的方法是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。最近几天在公司里写网络通讯的代码比较多,自然就会涉及到IO事件监测方法的问题。我...
    99+
    2023-06-16
  • linux fd指的是什么
    本篇内容主要讲解“linux fd指的是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“linux fd指的是什么”吧!在linux中,fd全称“File descriptor”,中文名为“文...
    99+
    2023-06-30
  • Ubuntu Linux系统的分区方法是什么
    这篇文章主要介绍“Ubuntu Linux系统的分区方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Ubuntu Linux系统的分区方法是什么”文章能帮助大家解决问题。一、Linux 分区...
    99+
    2023-06-16
  • Linux系统分析死锁的方法是什么
    这篇文章主要介绍“Linux系统分析死锁的方法是什么”,在日常操作中,相信很多人在Linux系统分析死锁的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux系统分析死锁的方法是什么”的疑惑有所...
    99+
    2023-06-28
  • Linux系统NFS配置的具体方法是什么
    Linux系统NFS配置的具体方法是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。NFS(Network File System)即网络文件系统,是FreeBSD支持的...
    99+
    2023-06-28
  • Linux系统下对目录扩容的方法是什么
    Linux系统下对目录扩容的方法是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 1、现象:日志服务器当初考虑不周,分区划分不太合理:2、目标:将/home磁...
    99+
    2023-06-28
  • Linux系统磁盘分区的表示方法是什么
    这篇文章的内容主要围绕Linux系统磁盘分区的表示方法是什么进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!在linux中使用fdisk -l 命令可...
    99+
    2023-06-28
  • 在Linux系统中配置Scala的具体方法是什么
    本篇文章为大家展示了在Linux系统中配置Scala的具体方法是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Scala是一种类似java的语言,曾经听到过会了java就等于会了Scala,这个...
    99+
    2023-06-28
  • Linux系统下SystemC环境配置方法
    以下为centos7下配置方法 下载systemc源码包:SystemC (accellera.org) 将压缩包放置到用户目录下,并解压 tar -zxvf systemc-2.3.3.tar.gz 进入到s...
    99+
    2022-06-04
    Linux系统SystemC环境 SystemC环境搭建
  • Linux系统下Nginx支持ipv6配置的方法
    一、查看现有nginx是否支持ipv6 需要执行以下命令,查看现有nginx是否支持ipv6,如果参数中具有--with-ipv6,则支持,如 果没有,则不支持,需要重新编译nginx。 # 此处的nginx路径以...
    99+
    2022-06-04
    Nginx支持ipv6 Nginx ipv6配置
  • linux系统下DHCP服务器的配置方法
    这篇文章主要讲解了“linux系统下DHCP服务器的配置方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“linux系统下DHCP服务器的配置方法”吧! 安装dhcp服务器软件Rh...
    99+
    2023-06-10
  • linux系统下vnc的配置及使用方法
    这篇文章主要讲解了“linux系统下vnc的配置及使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“linux系统下vnc的配置及使用方法”吧!VNC基本上是由两部分组成:一部分是客户端...
    99+
    2023-06-10
  • Linux系统缓存nscd的方法是什么
    本文小编为大家详细介绍“Linux系统缓存nscd的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Linux系统缓存nscd的方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。nscd最主要的作...
    99+
    2023-06-28
  • Linux系统运行PHP的方法是什么
    今天给大家介绍一下Linux系统运行PHP的方法是什么。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。Linux系统中如何运行 php 脚本?在 Linux 下...
    99+
    2023-06-28
  • Linux系统安装python3的方法是什么
    这篇“Linux系统安装python3的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Linux系统安装pytho...
    99+
    2023-06-28
  • linux系统安装mysql的方法是什么
    在Linux系统上安装MySQL的方法通常是通过包管理工具来实现。具体步骤如下: 打开终端(Terminal),输入以下命令更新系...
    99+
    2024-04-09
    linux mysql
  • Linux磁盘空间分配的方法是什么
    Linux系统中的磁盘空间分配方法主要是通过文件系统来管理磁盘空间的分配和使用。常见的文件系统包括ext4、XFS、Btrfs等。 ...
    99+
    2024-04-17
    linux
  • win10装系统分区的方法是什么
    在Windows 10上安装系统分区有以下几种方法:1. 使用Windows 10安装媒体:将Windows 10安装文件创建为启动...
    99+
    2023-09-28
    win10
  • Redhat Linux系统下磁盘配额的设置方法
    本篇内容主要讲解“Redhat Linux系统下磁盘配额的设置方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redhat Linux系统下磁盘配额的设置方法”吧!配额可以使各个用户和组无法占...
    99+
    2023-06-10
  • linux系统数据恢复的方法是什么
    这篇文章主要介绍“linux系统数据恢复的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“linux系统数据恢复的方法是什么”文章能帮助大家解决问题。工具: hexedit、fdisk下文内...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作