mirror of
https://github.com/d0zingcat/infloop.life.git
synced 2026-05-19 15:10:07 +00:00
35 lines
3.0 KiB
Markdown
35 lines
3.0 KiB
Markdown
---
|
||
title: "2018-10-24"
|
||
date: 2018-11-03T19:04:17+08:00
|
||
draft: true
|
||
---
|
||
|
||
> 本周继续学习GOPL,在讲到defer语句的时候提到了很有意思的一个概念,是Linux中的[file descriptor](https://en.wikipedia.org/wiki/File_descriptor)。简单来讲,linux在系统中都有一个唯一的id指向某个文件,例如0指向标准输入,1指向标准输出,2指向标准错误,3...从3开始,直接指向到开启文件。最大1024,换言之如果同时开启的文件太多超过1021,那么就会出现Linux File Descriptor 耗尽的问题。以下为全文:
|
||
|
||
**File Descriptor**
|
||
|
||
一个打开的文件通过唯一的描述符进行引用,该描述符是打开文件的元数据到文件本身的映射。在Linux内核中,这个描述符称为文件描述符(FileDescriptor),文件描述符用一个整数表示(C语言中的类型为int),简写为fd。文件描述符在用户空间(相对于内核空间而言,也就是我们应用程序的那层)中共享,允许用户程序用文件描述符直接访问文件。同一个文件能被不同或者相同的进程多次打开,每一个打开文件的实例(也就是java中的File类对象吧)都产生一个唯一的文件描述符。同一个描述符可以被多个进程使用。不同的进程能同时对一个文件进行读写,所以存在并发修改问题。
|
||
|
||
<!--more-->
|
||
|
||
每个进程都有个映射文件物理地址的表格(0标准输入 1标准输出 2标准错误 3、4、5....就映射你打开过文件的地址)
|
||
进程间怎么通过FileDescriptor共享文件: 子进程继承父进程 地址表格的(父进程调用fork 生成子进程)
|
||
|
||
内核为每一个进程维护一个打开文件的列表,称为文件表(File Table),索引是fd,数据为打开文件的信息(包括一个指向文件的Inode对象的指针,和相关元数据,如当前文件文职、读取模式)。(Inode包含文件的物理地址) 简单的讲,也就是有了Map结构,key是fd,value是文件的信息(包括物理地址、读取模式。。。。。)
|
||
子进程默认获得一份父进程FIle Table的拷贝,而 更改一个进程的FileTable不会影响另一个进程(如果子进程关闭了文件 不会影响父进程的File Table),所以fd可以用来共享文件。fd用C语言的int表示非负整数,从0开始递增 直到默认上限1024。按照惯例每个进程至少有三个打开的文件描述符,除非进程显式的关闭他们: 0 标准输入(stdin),1标准输出(stdout),2标准错误(stderr)。
|
||
|
||
*Conclusion*
|
||
|
||
1. fd的操作实际是系统内核API层次的,java的标准API没有直接相关的操作(据我已知,可以直接通过fd打开文件的)
|
||
2. 进程关联一个类似Map的文件表,key是fd,value是文件的物理地址等等信息。
|
||
3. 可以通过fd打开文件。
|
||
4. 子进程copy父进程的文件表
|
||
|
||
*Refer*
|
||
|
||
*Linux System Programming*
|
||
|
||
[FileDescriptor(文件描述符 )与Linux文件系统](https://blog.csdn.net/zhjali123/article/details/72566685)
|
||
|
||
|