每个进程开启一个soeket连接,都会占用一个文件描述符。
 
1. 概述
      在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。
      文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作(包括网络socket操作)的系统调用都通过文件描述符。
      程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号码,因此,在网络通信过程中稍不注意就有可能造成串话。标准文件描述符图如下:

 
文件描述与打开的文件对应模型如下图:
 
2. 文件描述限制
    在编写文件操作的或者网络通信的软件时,初学者一般可能会遇到“Too many open files”的问题。这主要是因为文件描述符是系统的一个重要资源,虽然说系统内存有多少就可以打开多少的文件描述符,但是在实际实现过程中内核是会做相应的处理的,一般最大打开文件数会是系统内存的10%(以KB来计算)(称之为系统级限制),查看系统级别的最大打开文件数可以使用sysctl -a | grep fs.file-max命令查看。与此同时,内核为了不让某一个进程消耗掉所有的文件资源,其也会对单个进程最大打开文件数做默认值处理(称之为用户级限制),默认值一般是1024,使用ulimit -n命令可以查看用户级文件描述符。在Web服务器中,通过更改系统默认值文件描述符的最大值来优化服务器是最常见的方式之一,具体优化方式请查看http://blog.csdn.net/kumu_linux/article/details/7877770
 
3. 文件描述符和打开文件之间的关系
    每个进程都拥有自己的文件描述符。  文件描述符的唯一性是进程+文件描述符ID确定的。
4. 内核维护的3个数据结构
 
    1. 进程级的文件描述符表
    2. 系统级的打开文件描述符表
    3. 文件系统的i-node表
 
进程级的描述符表的每一条目记录了单个文件描述符的相关信息。
    1. 控制文件描述符操作的一组标志。(目前,此类标志仅定义了一个,即close-on-exec标志)
    2. 对打开文件句柄的引用
 
内核对所有打开的文件的文件维护有一个系统级的描述符表格(open file description table)。有时,也称之为打开文件表(open file table),并将表格中各条目称为打开文件句柄(open file handle)。一个打开文件句柄存储了与一个打开文件相关的全部信息,如下所示:
    1. 当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)
    2. 打开文件时所使用的状态标识(即,open()的flags参数)
    3. 文件访问模式(如调用open()时所设置的只读模式、只写模式或读写模式)
    4. 与信号驱动相关的设置
    5. 对该文件i-node对象的引用
    6. 文件类型(例如:常规文件、套接字或FIFO)和访问权限
    7. 一个指针,指向该文件所持有的锁列表
    8. 文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳
 
下图展示了文件描述符、打开的文件句柄以及i-node之间的关系,图中,两个进程拥有诸多打开的文件描述符。
    在进程A中,文件描述符1和30都指向了同一个打开的文件句柄(标号23)。这可能是通过调用dup()、dup2()、fcntl()或者对同一个文件多次调用了open()函数而形成的。
    进程A的文件描述符2和进程B的文件描述符2都指向了同一个打开的文件句柄(标号73)。这种情形可能是在调用fork()后出现的(即,进程A、B是父子进程关系),或者当某进程通过UNIX域套接字将一个打开的文件描述符传递给另一个进程时,也会发生。再者是不同的进程独自去调用open函数打开了同一个文件,此时进程内部的描述符正好分配到与其他进程打开该文件的描述符一样。
    此外,进程A的描述符0和进程B的描述符3分别指向不同的打开文件句柄,但这些句柄均指向i-node表的相同条目(1976),换言之,指向同一个文件。发生这种情况是因为每个进程各自对同一个文件发起了open()调用。同一个进程两次打开同一个文件,也会发生类似情况。
 
5. 总结
    1. 由于进程级文件描述符表的存在,不同的进程中会出现相同的文件描述符,它们可能指向同一个文件,也可能指向不同的文件
    2. 两个不同的文件描述符,若指向同一个打开文件句柄,将共享同一文件偏移量。因此,如果通过其中一个文件描述符来修改文件偏移量(由调用read()、write()或lseek()所致),那么从另一个描述符中也会观察到变化,无论这两个文件描述符是否属于不同进程,还是同一个进程,情况都是如此。
    3. 要获取和修改打开的文件标志(例如:O_APPEND、O_NONBLOCK和O_ASYNC),可执行fcntl()的F_GETFL和F_SETFL操作,其对作用域的约束与上一条颇为类似。
    4. 文件描述符标志(即,close-on-exec)为进程和文件描述符所私有。对这一标志的修改将不会影响同一进程或不同进程中的其他文件描述符

文件描述符与socket连接的更多相关文章

  1. linux内核中的文件描述符(二)--socket和文件描述符

    http://blog.csdn.net/ce123_zhouwei/article/details/8459730 Linux内核中的文件描述符(二)--socket和文件描述符 Kernel ve ...

  2. linux文件描述符、软硬连接、输入输出重定向

    引用链接:https://blog.csdn.net/qq769651718/article/details/79459346 文件描述符的作用: 文件描述符是linux操作系统中特有的概念.其相当于 ...

  3. 一文帮你搞懂 Android 文件描述符

    介绍文件描述符的概念以及工作原理,并通过源码了解 Android 中常见的 FD 泄漏. 一.什么是文件描述符? 文件描述符是在 Linux 文件系统的被使用,由于Android基 于Linux 系统 ...

  4. Linux中通过Socket文件描述符寻找连接状态介绍

    针对下文的总结:socket是一种文件描述符 进程的打开文件描述符表 Linux的三个系统调用:open,socket,pipe 返回的都是一个描述符.不同的进程中,他们返回的描述符可以相同.那么,在 ...

  5. Linux内核Socket实现之------Socket创建(2) 文件描述符

    转载请注明:http://blog.chinaunix.net/uid-20788636-id-4408276.html 1.2 sock_map_fd函数 在用户空间创建了一个socket后,返回值 ...

  6. Linux下文件描述符

    http://blog.csdn.net/kumu_linux/article/details/7877770 文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket.第一个打开的 ...

  7. Linux系统学习笔记:文件描述符标志

    文件描述符标志的概念 文件描述符标志(目前就只有一个close-on-exec): 它仅仅是一个标志,当进程fork一个子进程的时候,在子进程中调用了exec函数时就用到了这个标志.意义是执行exec ...

  8. Linux下的文件描述符

    文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket.第一个打开的文件是0,第二个是1,依此类推.Unix 操作系统通常给每个进程能打开的文件数量强加一个限制.更甚的是,unix ...

  9. accept 文件描述符用尽处理

    if (events[i].data.fd == listenfd) { peerlen = sizeof(peeraddr); connfd = ::accept4(listenfd, (struc ...

随机推荐

  1. [04] css 选择器

    1.元素选择器 常见的html标签元素 h1 { color: red; } body { background: red; } 2.分组选择器 例如body和h2标签的字体颜色都是red,使用逗号将 ...

  2. JS知识总结

    1.javascript继承机制 原型继承,访问对象属性时,如果对象内部有就返回,找不到就会从对象原型指向的对象原型中查找,一层一层的查找,直到最顶层的对象原型还找不到,就返回undefined. 2 ...

  3. 创建 React 项目

    依次输入命令: npm install -g create-react-app create-react-app react16 cd my-app npm start 在浏览器中输入 local:3 ...

  4. 【STSRM13】木之本樱

    [题意]抽象模型后转化为:给定n个直线,ans+=C(x,4)*8,x为每个经过直线数>=4的点的直线数,不存在平行直线. [算法]数学 [题解] 运用了一个很简单的道理:经过同一个点的线段互相 ...

  5. 160多条Windows 7 “运行”命令

    160多条Windows 7 “运行”命令: 删除或更改应用程序 = control appwiz.cpl 添加设备 = devicepairingwizard  蓝牙文件传输 = fsquirt  ...

  6. Django【进阶】缓存

    Django缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者me ...

  7. LeetCode 191:number of one bits

    题目就是: Write a function that takes an unsigned integer and returns the number of ’1' bits it has (als ...

  8. mysql五-1:单表查询

    一 介绍 本节内容: 查询语法 关键字的执行优先级 简单查询 单条件查询:WHERE 分组查询:GROUP BY HAVING 查询排序:ORDER BY 限制查询的记录数:LIMIT 使用聚合函数查 ...

  9. 24式太极拳:3D动画演示(图文)

    http://blog.sina.com.cn/s/blog_4be33b740102e9ae.html 24式太极拳:3D动画演示(图文) (2013-03-10 18:45:55) 转载▼ 标签: ...

  10. HDU-5074

    Hatsune Miku Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)To ...