文件描述符限制 文件描述符 Linux的核心思想之一就是”一切皆文件”。 文件描述符(文件句柄)是Linux内核为了高效管理已被打开的文件所创建的索引,它是一个非负整数,用于指代被打开的文件。文件打开后,所有对该文件的操作都通过文件描述符进行操作。 文件描述符是系统的重要资源,当打开过多文件时会出现把系统内存耗尽的情况,所以Linux提供了多种维度对文件描述符的使用上限进行限制,以避免该问题。 文件描述符限制 file-max file_max用于限制整个系统能够分配的文件描述符,即当前系统下所有用户下的所有进程,其分配的所有文件描述符之和不能超过该值。 ,它记录了当前系统中文件描述符的使用情况,第一个(6144)是系统已经分配的文件描述符数;第二个(0)是系统已经分配但未使用的文件描述符数;第三个是内核最大能分配的文件描述符数,与file-max一致。
最近由于机缘巧合,结合最近工作中遇到的一些问题,深入了解了文件描述符(File Descriptor,简称FD,以下使用 FD 称谓)。预计会有两到三篇关于 FD 的文章陆续出来。 概念定义 文件描述符 是 用来访问资源(文件,输入输出设备等)的一种抽象指示符。 文件描述符 是POSIX(Portable Operating System Interface)规范的组成部分 文件描述符 通常是非负整数,C 语言中使用int类型。 当我们尝试打开文件/path/myfile.txt 1.从inode table 中查找到对应的文件节点 2.根据用户代码open的一些参数(比如读写权限等)在open file table 中创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
文件描述符定义文件描述符就是文件句柄,类似于指针指向具体的文件或者键盘等注意不同的进程有自己完全独立的文件描述符表同一进程的多个文件描述符可能会指向同一文件不同进程的多个文件描述符可能也会指向同一文件标准文件描述符文件描述符缩写描述 file将commands的错误信息重定向到file中2>就是错误重定向2是错误文件描述符ex控制台输出输出到文件输出追加到文件#控制台输出,将ls-lf11命令的结果输出到f1文件,由于f11不存在, f2,f2直接被清空了$catf2创建文件描述符exec命令(内置命令)作用替换当前shell进程,执行新的程序重定向当前shell的文件描述符格式exec[-cl][-aname][command[argument /bin/bash#创建文件描述符5为标准输入exec5<&0exec0<f2#0文件描述符输入源为f2#while循环打印出的都是f2文件的信息whilereadlinedoecho"readinfo /bin/bashexec3<f2#创建输入文件描述符3read-p"showmsg:"line<&3echo"$line"exec3>&-#关闭文件描述符3read-p"pleaseinputnewchar
2. ulimit 查看进程允许打开的最大文件句柄数:ulimit -n 设置进程能打开的最大文件句柄数:ulimit -n xxx ulimit在系统允许的情况下,提供对特定shell可利用的资源的控制 该文件描述符用于确保每次只能打开一个应用程序实例。初始打开每个应用程序时,都有三个文件描述符:0,1,2,分别表示标准输入、标准输出、错误流。所以大多数应用程序所打开的文件的FD都是从3开始的。 查看当前进程打开了多少文件:lsof -n|awk ‘{print $2}’|sort|uniq -c|sort -nr|more | grep [PID] ? 通常,一个进程启动时,都会打开3个文件:标准输入、标准输出和标准出错处理。这3个文件分别对应文件描述符为0、1和2(宏STD_FILENO、STDOUT_FILENO和STDERR_FILENO)。 进程级的文件描述符表 2. 系统级的打开文件描述符表 3.
不同位置的变量在内存中的排布”,其中在内核地址空间中,维护着一个 PCB 进程控制块,其中包含很多进程相关的信息,比如进程ID、用户ID、组ID等等,但本文我们最关注的,是 PCB 进程控制块中维护的一份“文件描述符表 图片 图中右侧表示的,就是我们今天讨论的主题“文件描述符表”,其内部有0~1023个id可以提供用户申请分配,每当用户使用一个 open 操作打开一个文件时,都会返回一个文件描述符,比如如下代码: int nRet = open("/dev/zero", O_RDONLY); 这句代码会在当前进程内核区文件描述符表中申请一个新的文件描述符赋值给nRet值,系统默认情况下会帮我们打开三个文件描述符, 0代表是标准输入、1代表是标准输出、2代表标准Error。 file 的值设定为2048了,这样我们每个程序就可以打开0~2047个文件描述符了(这种情况很少见)。
, 比如文件、资源、菜单、光标、位图等 那么,现在你应该可以理解文件描述符的含义了 文件描述符 之于文件系统(操作系统中的一切都是文件描述符 可以使用文件描述符描述任何一个资源对象 就如同 其实说白了,就是文件描述符的实例,就是用来表示文件的一个指针/索引. 显然不行,必须是运营商提供给你的 我们的文件描述符,也是如此,应用程序不应该创建自己的文件描述符 他的构造方法,只能创建一个无效的文件描述符 不应该创建自己的文件描述符,可以直接理解为: 具体的值是 0 1 2 ,这是操作系统层面的描述 在linux 中, 每个进程启动时都打开3个文件(linux 中一切都是文件): * 标准输入 0 * 标准输出 1 * 标准错误 2 三个描述符,通过调用私有方法 standardStream进行创建初始化 创建一个FileDescriptor 并且,设置他的handle值 内部的set
在Linux编程世界中,不可能没听过文件描述符这个概念,我们操纵任何设备的时候,几乎都要通过它来达成的,它究竟是何方神圣呢?随我描述符科学家来一探究竟。 首先,我们在Linux下打开文件用的都是如下代码: int fd = open(... ...); 当然有同学可能会说,有时也可以用fopen(),但是fopen()只是标准IO对系统IO的封装,归根结底还是使用 open()来打开一个文件。 很多人就想当然地以为打开嘛,就跟在windows下双击一个文件,或者双击一个文件夹一样,就是一个动作而已,其实不然,常说的打开一个文件实际上最重要的是获取这个文件的描述符,描述符是用来表征这个文件的代表物 内核空间中有一堆数据结构表达一个文件的属性信息,但是用户空间看不见,只看见一个代表了这些信息的整数i,通常我们称之为文件描述符,对文件的读写和ioctl操作都是通过这个东东来达到的呢!
Linux标准文件描述符 文件描述符 缩写 描述 0 STDIN 标准输入 1 STDOUT 标准输出 2 STDERR 标准错误输出 ---- Linux系统将所有设备都当作文件来处理,而Linux 那么我们可以把上面表格中的文件描述符0理解为我和计算机交互时的输入,而这个输入默认是指向键盘的; 文件描述符1理解为我和计算机交互时的输出,而这个输出默认是指向显示器的;文件描述符2理解为我和计算机交互时 只不过我们需要把上面标准输出的1改成2,命令如下: exec 2> xlinsist1 当然,除了0, 1,2以外,我们可以分配自己的文件描述符。 因此文件描述符3也指向了显示器。然后,我们修改了文件描述符1指向的文件到test文件。 文件描述符相关的一些shell命令 lsof -a -p $$ -d 0,1,2 #下面为这个命令的输出 COMMAND PID USER FD TYPE DEVICE SIZE/OFF
重定向的实质 1和2的区别 在 Linux 系统中,文件描述符(File Descriptor, FD)是一个非负整数,用于标识打开的文件、输入/输出设备或其他资源。 标准输入、标准输出和标准错误是最常用的文件描述符,其对应的值为 0、1 和 2,具体含义和使用说明如下: 文件描述符的含义 标准输入(stdin) 描述符: 0 用途: 接收输入数据,通常是来自键盘的用户输入 使用示例 以下是一些文件描述符的常见使用示例: 1. 基本输出 bash # 将字符串输出到标准输出 echo "This is standard output" 2. go to the file" > same_output_and_error.txt 2>&1 相关系统调用 在编程中,你还可以使用系统调用来操作文件描述符,以下是一些常用的: open(): 打开文件并返回文件描述符 分配规则: 当进程启动时,默认会打开三个文件描述符:标准输入(stdin,文件描述符为0)、标准输出(stdout,文件描述符为1)、标准错误(stderr,文件描述符为2)。
在Linux操作系统中,一切皆是文件—— "Everything is a file"。 如果要在Linux系统中编写操作文件的代码,需要借助文件描述符。 文件的索引——文件描述符(file descriptor): 文件描述符是一个非负整数,当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。 文件描述符就是内核为了高效管理已被打开的文件所创建的索引值。 文件描述符指向内核为每一个进程维护的打开文件记录表。当要处理文件时,将文件对应的文件描述符作为参数传给函数。 文件描述符在用户进程和内核之间的映射关系: Linux中查看文件描述符的指令:lsof(list open files) lsof可以打开的文件: 普通文件 目录 网络文件系统的文件 字符或设备文件 - O_TRUNC 如果文件已存在,并且以只写或可读可写方式打开,则将其长度截断为0字节 [mode_t mode] : 文件权限,只有在创建文件时需要使用 return: 文件描述符
一.简介 每个进程开启一个soeket连接,都会占用一个文件描述符。 文件描述符的唯一性是进程+文件描述符ID确定的。 文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作(包括网络socket操作)的系统调用都通过文件描述符 程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。 这主要是因为文件描述符是系统的一个重要资源,虽然说系统内存有多少就可以打开多少的文件描述符。 在Web服务器中,通过更改系统默认值文件描述符的最大值来优化服务器是最常见的方式之一。
三.内核维护的3个数据结构 1.进程级的文件描述符表 2.系统级的打开文件描述符表 3.文件系统的i-node表 进程级的描述符表的每一条目记录了单个文件描述符的相关信息。 在进程A中,文件描述符1和30都指向了同一个打开的文件句柄(标号23)。这可能是通过调用dup()、dup2()、fcntl()或者对同一个文件多次调用了open()函数而形成的。 进程A的文件描述符2和进程B的文件描述符2都指向了同一个打开的文件句柄(标号73)。 四.总结 由于进程级文件描述符表的存在,不同的进程中会出现相同的文件描述符,它们可能指向同一个文件,也可能指向不同的文件 两个不同的文件描述符,若指向同一个打开文件句柄,将共享同一文件偏移量。 文件描述符标志(即,close-on-exec)为进程和文件描述符所私有。对这一标志的修改将不会影响同一进程或不同进程中的其他文件描述符
fd.pdf 众所周知,子进程会继承父进程已经打开的文件描述符fd,但是fork之后的是不会被继承的,这个时候是否无能无力了?答应是NO。 Linux提供了一个系统调用sendmsg,借助它,可以实现进程间传递文件描述符fd,而且不仅限于父进程到子进程。
Linux系统下进程会默认打开三个文件,即标准输入、标准输出、标准错误,分别对应文件描述符0 1 2。 这也是为什么我们打开文件时,返回的文件描述符是从3开始,因为前面的0 1 2已经被占用了 一个文件可以在同一个进程中被打开对此,也就意味着不同的文件描述符,可能会指向同一个文件。 dup2函数实现重定向 上面我们这种close一个文件,再打开一个文件,以此来更改文件描述符对应的文件指向,这种方法多多少少有一些不方便,而且也挺挫的。 所以假如我们要将1号文件描述符的指向的文件修改为fd对应的文件,应该这样来写:dup2(fd,1),这就是输出重定向,当然输入重定向就是:dup2(fd,0)。 dup2原理: dup2函数的原理实际上就是通过拷贝的方式,修改原来文件描述符表中特定下标所指向的文件,这里需要注意一点的是,dup2函数在实现重定向时,会先将原有的文件描述符指向的对应的文件关闭,这样避免内存泄漏问题的出现
所以,只要拿着文件描述符,就可以找到对应的文件 。 Linux中一切皆文件,所以0,1,2可以代表键盘,显示器。 在OS内,系统在访问文件的时候,只认文件描述符fd。 read的返回值:>0 :读取到的字节数 =0:已经读取到文件末尾。 文件描述符的分配规则 因为文件描述符的0、1、2默认是打开的,所以这里结果是3。 如果我们先把描述符0关了再打开新文件会怎样呢? 如果我们把2先关了 ,这时候结果就是2了。 由于我们先关闭了文件描述符1,所以此时log.txt的文件描述符就是1。 使用 dup2 系统调用 dup2可以在底层帮我们做两个文件描述符对应的数组内容之间的值拷贝 。 本质是文件描述符下标对应内容的拷贝。
通过fd命令,我们可以查看当前进程所打开的文件描述符及其相关信息,包括文件描述符的编号、打开模式、文件路径等。图片2. 语法使用fd命令的语法如下:fd [选项]3. 0对应/dev/null,文件描述符1和2对应/dev/pts/1,文件描述符3对应/home/user/file.txt,文件描述符4对应/home/user/output.txt。 以下是一个示例:$ fd -p0 r1 w2 w3 rw4 w在这个示例中,文件描述符0以只读(r)模式打开,文件描述符1和2以写入(w)模式打开,文件描述符3以读写(rw file在这个示例中,文件描述符0、1和2是字符设备(character device)类型的文件描述符,文件描述符3和4是普通文件(regular file)类型的文件描述符。 4.4 显示所有文件描述符的详细信息使用fd -e命令可以显示当前进程的所有文件描述符的详细信息,包括文件描述符编号、打开模式、文件路径等。
1.文件描述符 fd 1.1文件打开的返回值fd(重点) 我们可以看到,这三大数据流是来自于C标准库的,类型又是一个我们从来没有听说过的FILE类型。 fd==1. 1.4.dup2()函数 参数:oldfd:要被复制的文件描述符;newfd:目标文件的描述符。 返回值:成功,返回新的文件描述符(即:newfd)。出错时,返回 -1,并设置 errno以指示错误。 功能:就是将新的文件描述符变成旧的文件描述符的一份拷贝拷贝。 int main() 79 { 80 int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666); 81 82 dup2(fd,1); 现象2解释:重定向到普通文件时,数据刷新缓冲区的方式,由行缓存变为全缓冲,C语言接口自带缓冲区,所以它会将数据写入到缓冲区中,就不会立即刷新。
maxsyslogins/priority/locks/sigpending/msgqueue/nice/rtprio/ value: -1/unlimited/infinity/ 具体值 要修改最大文件描述符重点在于 item和value 2.修改 ---- 2.1 先查看当前用户最大文件描述符数量: 1 ulimit -Hn 2 ulimit -Sn 2.2 修改当前用户进程的最大文件描述符数量: 1 vim /etc/security/limits.conf 2 在末尾添加 3 user soft nofile 4096 (user为用户名) 4 user hard nofile 10240
今天介绍下什么是文件描述符(File Description) 每天多知道一点点 由于是纯理论知识,所以分点来总结: 1、概念:文件描述符是操作系统内核用于管理已经打开的文件而创建的索引。 它是一个非负整数 2、描述符 0 表示标准输入、1 是标准输出、2 是标准错误,所以新打开一个文件是从 3 开始索引 3、每个描述符一定会对应一个打开的文件,而不同的描述符(即索引值)也可能指向同一个打开的文件 原因是同一个文件可以在多进程中打开,而系统为每个进程都维护了一个文件描述符表,这个表都是从 0 开始索引的 4、重点:如何查看当前进程下文件描述符 #pid为进程号 /proc/$pid/fd #lsof 命令 COMMAND:进程的名称 PID:进程标识符 USER:进程所有者 FD:文件描述符,应用程序通过文件描述符识别该文件。 如cwd、txt等 TYPE:文件类型,如DIR、REG等 DEVICE:指定磁盘的名称 SIZE:文件的大小 NODE:索引节点(文件在磁盘上的标识) NAME:打开文件的确切名称 5、文件描述限制
文本写入 vs 二进制写入 我们在往显示器上打印12345的时候是往显示器打印的是1字符2字符3字符4字符和5字符。而不是一万两千三百四十五。 访问文件的本质 我们一次性打开四个文件,并观察它的fd 打出来的文件描述符是3,4,5,6问题是0,1,2去哪里了呢? 0:标准输入 1:标准输出 2:标准错误 这三个叫做默认的文件流,因为它默认的把三个文件打开了,012已经被占了。 FILE是C语言提供的一个结构体,它是被typedef出来的,结构体里包含了文件的属性。 在OS接口层面上只认fd文件描述符,所以这个结构体里一定封装了文件描述符。 文件描述符的分配原则:最小的没有被使用的作为新的fd分配给用户。