文件
文件是 OS 的核心抽象之一,本质上是将进程与各种设备和组件之间的交互转换为在文件上的二进制数据。
也就是对上层的软件屏蔽了所有的底层实现,通过管道(pipe),让进程与底层间通过文件上的二进制数据进行流转。
文件可以被多个进程共享,在软件的基础上进一步抽象出:文件描述符(file description,缩写 fd)。fd 是对文件的一个视图,包含文件指向和偏移量。其中,偏移量是隐式维护的。
TIP
Kafka中抽象的Topic,也是通过consumer维护一个关联到Topic的偏移量,用于表示当前已消费的内容。
Q:不管是多进程还是 Kafka 中的 consumer 都会涉及同时写入同一个文件的问题,那么都是怎么解决的呢?
文件描述符是一个进程范围的整数。我们固定 0 是标准输入,1 是标准输出。这样可以通过管道来将数据流重定向,从而对不同的处理过程(cmd)进行自由组合。我们以常用的 lsof | grep 'Surge' 命令作为拆解:
grep作为我们本次使用的处理过程,只用于对数据流进行查找操作,因为每个处理工具都只需要关注一件小事;- 通过管道重定向 lsof 的输出到
grep的输入:需要输入就从标准输入读取,需要输出就输出到标准输出; - 管道负责将一个个小工具串成一个复杂的处理过程。
文件操作语义
open:以指定模式打开文件,会返回一个相应的文件描述符,并且隐式初始化该fd的offset为 0;read(fd, buf, n):从文件描述符fd关联的文件的偏移量处读取最多n个字节到buf中;读取成功后会前移fd关联的偏移量。对调用者来说无需要关心偏移量的变更,只需要不断读取fd的内容即可,读取成功会返回实际读到的字节数;如果失败,则返回值小于 0;write(fd, buf, n):将buf中的n个字节内容写入到文件描述符fd关联的文件和偏移量处;并且会自动前移fd相应字节的偏移量,写入成功会返回n;如果失败,返回值小于n;close(fd):释放fd和所占用的资源,比如文件指针和偏移量等信息。且进程之后可以复用该fd标号。