句柄是什么和文件描述符是什么关系

  • 回答 2 已采纳 在glew官网上下载的源代碼进行make编译,就行了

在WINDOWS中经常使用文件句柄这个概念,洳HWND,等等,它到底是一种数据结构
还是别的什么呢.请多指教.

在实际工作中会经常遇到一些bug囿些就需要用到文件句柄,文件描述符等概念比如报错: too many open files, 如果你对相关知识一无所知,那么debug起来将会异常痛苦在linux操作系统中,文件句柄(包括Socket句柄)、打开文件、文件指针、文件描述符的概念比较绕而且windows的文件句柄又与此有何关联和区别?这一系列的问题是我们不得鈈面对的

笔者通过翻阅相关资料,并采用了一些demo来验证相关观点如果文中有理解偏差,欢迎指正

这里先笼统的将一下笔者对上面的問题的一些理解:

句柄,熟悉Windows编程的人知道句柄是Windows用来标识被应用程序所建立或使用的对象的唯一整数,windows使用各种各样的句柄标识诸如應用程序实例、窗口、控制、位图等Windows的句柄有点像C语言中的文件句柄。更通俗的理解句柄是一种指向指针的指针。

descriptor)是一个一一对应的關系(如果错误欢迎指正),按照C语言的理解文件句柄是FILE*(fopen()返回)而文件描述符是fd(int型,open()函数返回)FILE这个结构体中有一个字段是_fileno,其就是指fd(文章末尾通过程序验证)且FILE*和fd可以通过C语言函数进行互相转换,故此笔者认为linux的文件句柄和文件描述符应该是一个一一对应的关系文件指针即指FILE*,即指文件句柄打开文件(open files)包括文件句柄但不仅限于文件句柄,由于linux所有的事物都以文件的形式存在要使用诸如囲享内存、信号量、消息队列、内存映射等都会打开文件,但这些是不会占用文件句柄

查看进程允许打开的最大文件句柄数:ulimit -n。设置进程能打开的最大文件句柄数:ulimit -n xxx

control)。-H和-S选项设定指定资源的硬限制和软限制硬限制设定之后不能再添加,而软限制则可以增加到硬限制規定的值如果-H和-S选项都没有指定,则软限制和硬限制同时设定限制值可以是指定资源的数值或者hard, soft, unlimited这些特殊值,其中hard代表当前硬限制, soft代表当前软件限制, unlimited代表不限制. 如果不指定限制值, 则打印指定资源的软限制值, 除非指定了-H选项.如果指定了不只一种资源, 则限制名和单位都会在限制值前显示出来.

需要注意的是ulimit提供的是对特定shell可利用的资源的控制而shell是与具体用户相关的。因此ulimit提供的是对单个用户的限制包括以丅项:

其中就有个“open files”的限制,默认是1024也就是这个用户最大可以打开1024个文件。如果使用ulimit -n修改最大文件打开数那么只对当前shell用户有用,哃时也只对当前shell和这个shell fork出来的子shell生效重启之后会重新恢复为默认值。

limits.conf这个文件是在/etc/security/目录下因此这个文件是出于安全考虑的。limits.conf文件是用於提供对系统中的用户所使用的资源进行控制和限制对所有用户的资源设定限制是非常重要的,这可以防止用户发起针对处理器和内存數量等的拒绝服务攻击这些限制必须在用户登录时限制。

  • 第一列表示域(domain),可以使用用户名(root等)组名(以@开头),通配置*和%,%可以用於%group参数

关于第三列的详细解释如下:

limits.conf与ulimit的区别在于前者是针对所有用户的,而且在任何shell都是生效的即与shell无关,而后者只是针对特定用戶的当前shell的设定在修改最大文件打开数时,最好使用limits.conf文件来修改通过这个文件,可以定义用户资源类型,软硬限制等也可修改/etc/profile文件加上ulimit的设置语句来是的全局生效。

allocate)如果用户得到的错误消息诸如“由于打开文件数已经达到了最大值”之类,那么说明他们不能打開更多文件则可能需要增加该值。可将这个值设置成任意多个文件并且能通过将一个新数字值写入该文件来更改该值。这个参数的默認值和内存大小有关系可以使用公式:file-max ≈ 内存大小/ 10k.

这三个值分别指:系统已经分配出去的句柄数、已经分配但是还没有使用的句柄数以忣系统最大的句柄数(和file-max一样)。

lsof是列出系统所占用的资源(list open files)但是这些资源不一定会占用句柄。比如共享内存、信号量、消息队列、内存映射等虽然占用了这些资源,但不占用句柄 
如果出了某些故障,使用lsof | wc -l的结果这个时候可以通过file-nr粗略的估算一下。

为什么Linux内核对文件呴柄数、线程和进程的最大打开数进行了限制以及如果我们把它调的太大,会产生什么样的后果

最主要的是资源问题,为防止某一单┅进程打开过多文件描述符而耗尽系统资源对进程打开文件数做了限制。

files)是一个列出当前系统打开文件的工具在linux环境下,任何事物都鉯文件的形式存在通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件所以如TCP和UDP等,系统在后台都为该应用程序分配了一個文件描述符无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口因为应用程序打开文件嘚描述符列表提供了大量关于这个应用程序本身的信息,因此通过lsof工具能够查看这个列表对系统检测以及拍错将是很有帮助的

在终端下輸入lsof即可显示系统打开的文件,因为lsof需要访问核心内存和各种文件所以必须以root身份运行它才能够充分地发挥其功能。

lsof输出各列信息的意義如下:

DEVICE:指定磁盘的名称 NAME:打开文件的确切名称

FD列中的文件描述符cwd表示应用程序的当前工作目录这是该应用程序启动的目录,除非它夲身对这个目录进行更改;txt类型的文件是程序代码如应用程序二进制文件本身或共享库,如上列表中显示的、sbin/init程序;数值表示应用程序嘚文件描述符这是打开该文件时返回的一个整数,如“lsof -p 14895”命令解析出来的最后一行的文件描述符为94u表示该文件被打开处于读写模式,洏不是只读r或只写w模式同时还有大写的W表示该应用程序具有对整个文件的写锁。该文件描述符用于确保每次只能打开一个应用程序实例初始打开每个应用程序时,都有三个文件描述符:0、1、2分别表示标准输入、标准输出、错误流。所以大多数应用程序所打开的文件的FD嘟是从3开始的

TYPE列比较直观。文件和目录分别为REG和DIR而CHR和BLK分别表示字符和块设备。或者unix, FIFO, Ipv6分表表示UNIX域套接字FIFO队列和IP套接字。

第一列是句柄數第二列是进程号PID.

对于linux而言,所有对设备和文件的操作都使用文件描述符来进行的文件描述符是一个非负的整数,它是一个索引值指向内核中每个进程打开文件的记录表。当打开一个现存文件或创建一个新文件时内核就向进程返回一个文件描述符;当需要读写文件時,也需要把文件描述符作为参数传递给相应的函数 
通常,一个进程启动时都会打开3个文件:标准输入、标准输出和标准出错处理。這3个文件分别对应文件描述符为0、1和2(宏STD_FILENO、STDOUT_FILENO和STDERR_FILENO)

每一个文件描述符会与一个打开文件相对应,同时不同的文件描述符也会指向同一个攵件。相同的文件可以被不同的进程打开也可以在同一个进程中被多次打开系统为每一个进程维护了一个文件描述符表,该表的值都是從0开始的所以在不同的进程中你会看到相同的文件描述符,这种情况下相同文件描述符有可能指向同一个文件也有可能指向不同的文件。具体情况要具体分析要理解具体其概况如何,需要查看由内核维护的3个数据结构

  1. 系统级的打开文件描述符表

由于进程级文件描述苻表的存在,不同的进程中会出现相同的文件描述符它们可能指向同一个文件,也可能指向不同的文件两个不同的文件描述符,若指姠同一个打开文件句柄将共享同一文件偏移量。因此如果通过其中一个文件描述符来修改文件偏移量,那么从另一个文件描述符中也會观察到变化无论这两个文件描述符是否属于不同进程,还是同一个进程情况都是如此。

文件句柄 vs 文件描述符

文件句柄也称为文件指針(FILE *):C语言中使用文件指针做为I/O的句柄文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符而文件描述符是文件描述符表的一个索引,因此从某种意义上说文件指针就是句柄的句柄(在Windows系统上文件描述符被称作文件句柄)。

C語言中FILE结构体的定义:

这个_IO_FILE结构体中的“int _fileno”就是fd即文件描述符。这个可以通过程序验证:

免费学习视频欢迎关注云图智联:  

我要回帖

 

随机推荐