一、文件描述符 - 1、概念: 在linux下一切皆文件的思想,文件被分为普通文件,目录文件,链接文件和设备文件。 文件描述符是内核为了高效管理已被打开的文件所创建的索引,它是一个非负整数,用于指代被打开的文件,所有执行I/O操作的系统调用都要通过文件描述符。 程序刚启动的时候,0,1,2分别表示标准输入,标准输出,标准错误。因此此时当我们打开一个文件的时候,他的文件描述符是3。
2、如何作用: fd是一个整数,在open的时候产生,起到一个索引的作用,通过进程的task_struct中保存的文件描述符表找到该fd所指向的文件指针以打开文件的指针。
3、注意: 从当前我使用的最小整数处开始分配
二、文件描述的限制
系统限制:一般最大打开文件数是系统内存的10%(以kB来算的) 可以用命令查看:sysctl -a |grep fs.file-max
用户限制:为了不让一个进程消耗掉所有的文件资源,也会对单个进程最大打开文件数做默认处理,一般默认1024 可以用命令查看:ulimit -n
三、文件描述符和打开文件之间的关系:
简单来说:在open的时候产生,起到一个索引的作用,通过进程的task_struct中保存的文件描述符表找到该fd所指向的文件指针以打开文件的指针。
不同的进程会有相同的文件描述符,相同的文件描述符又可能指向同一个文件,也可能指向不同的文件。 每一个文件描述符会与一个打开文件相对应,不同的文件描述符也会指向同一个文件。 相同的文件可以被不同的进程打开也可以在同一个进程中被多次打开 那么我们就要进行具体的分析,需要查看有内核维护的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. 文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳
四、文件描述符的优缺点:
1)优点:很多系统都兼容 2)缺点:由于是系统调用,因此移植性很差
1、是指进程的用户空间中一个FILE结构的数据结构,它主要包括一个I/O缓冲区和文件描述符,而文件描述符是文件描述符表的一个索引指针,因此文件指针是句柄中的句柄。
2、优点:便于移植,通用于c语言的格式
3、FILE结构: struct _iobuf { char *_ptr; //缓冲区当前指针 int _cnt; char *_base; //缓冲区基址 int _flag; //文件读写模式 int _file; //文件描述符 int _charbuf; //缓冲区剩余自己个数 int _bufsiz; //缓冲区大小 char *_tmpfname; }; typedef struct _iobuf FILE;
1、文件描述符和文件指针之间的转化: 既然FILE结构中含有文件描述符,那么可以使用fopen来获得文件指针,然后从文件指针获取文件描述符,文件描述符应该是唯一的,而文件指针却不是唯一的,但指向的对象是唯一的。 eg: int fd = open(“TAGS”, O_RDONLY); FILE * fp = fopen(“TAGS”, “r”); printf(“%d %d\n”, fd, fp->_file);
2、文件描述符和文件指针的关系: 文件指针包含文件描述符
