文件系统
文件索引节点:inode
两部分 纯数据区
- 文件真正的数据存储区、基本存储单位为block
元数据区
- 文件属性:磁盘中的存储位置、文件长度等信息
- 时间戳:创建时间、修改时间
- 读写权限:使用read/write系统调用时,要首先要进行权限检
- 所属组、所有者
- 链接数
挂载
挂载是一个非常重要的功能,使用非常频繁。它指将一个设备(通常是存储设备,可以挂载光盘、硬盘、磁带、光盘镜像文件等)挂接到一个已存在的目录上,那么,你访问这个目录就是访问这个设备(这个目录可以不为空,但挂载后这个目录下以前的内容将不可用) ,一个目录一旦成为"挂载点",该目录下看到的内容,来自"被挂载的文件系统", 与父目录的存储介质完全无关。
挂载需要有 挂载源(设备) 和 挂载点(目录)
/var → /dev/mtdblock5 (JFFS2 flash)
/var/run → tmpfs (RAM)
/var/run/hdd0 → /dev/sda2 (HDD / ext2)
进程间通信

通过文件
通过内核
共享内存
匿名管道

匿名管道是一种只用于亲缘关系进程间、基于内核缓冲、半双工、顺序可靠的字节流通信方式,读写都会阻塞,必须注意正确关闭读写端才能避免死锁。
匿名管道的基本用法
- 创建匿名管道
int pipe_fd[2];
pipe(pipe_fd); // pipe_fd[0] = 读端, pipe_fd[1] = 写端
- fork 之后由父子进程各关闭不需要的端口
- 写数据的进程:关闭读端
- 读数据的进程:关闭写端
否则 read/write 行为会受到影响(例如 EOF 不会出现)
- 父子通过 read / write 进行通信
write(pipefd[1], buf, n)read(pipefd[0], buf, n)
匿名管道的阻塞行为(重点)
Write 可能阻塞的情况:
- 管道缓冲区已满时,write 阻塞,只有当读进程读走数据后,write 才能继续
Read 可能阻塞的情况:
- 管道缓冲区为空 → read 阻塞,直到写进程写入更多数据
- 如果写端全部关闭 → read 返回 0(代表 EOF)
匿名管道的注意事项
- 必须正确关闭端口,否则会出现以下情况:
- 读端不关闭写端 ⇢ 读不到 EOF,一直阻塞
- 写端不关闭读端 ⇢ 异常行为,甚至 SIGPIPE
- 管道大小有限 ,一般为64KB
- 匿名管道不能用于非亲缘进程
- 多个写端写入时是原子化的?
- 小于
PIPE_BUF(通常 4096 字节)的写入是原子的 - 大写可能导致数据交错
- 小于
- 管道是流式无格式通信,没有消息边界,需要自己定义协议格式(分包、长度)
问:如果读端进程已经关闭(close(pipefd[0])),写进程继续 write 会发生什么?
答 write 失败,收到 SIGPIPE
因为匿名管道有一个特殊规则:
- 规则:当所有读端被关闭时:
- write 不再阻塞
- write 立即返回错误:
EPIPE - 并向进程发送
SIGPIPE信号- → 如果进程没有处理该信号,会被终止!
- 这就是“Broken Pipe”错误的来源。
写端写管道时,如果所有读端都关闭,write 不会阻塞,而是立即失败,并收到 SIGPIPE。
例如:
每个进程各关闭一端,我们强制建立了一个明确的单向通信流:子进程 -> 父进程。
- 对于读者(父进程): 只有当所有指向管道写端的文件描述符都被关闭时,读者在读取管道时才会接收到 EOF(文件结束符)。如果父进程不关闭自己的
fds[1],那么即使子进程退出了(关闭了它的fds[1]),管道的写端依然被父进程自己持有着。这样,父进程在读取fds[0]时永远不会拿到 EOF,可能会导致程序死锁,一直在等待永远不会到来的数据。 - 对于写者(子进程): 如果读者(父进程)关闭了读端,子进程再尝试写入数据时,操作系统会向子进程发送
SIGPIPE信号,表明管道已断开。
命名管道 FIFO
与匿名管道不同,有文件名,FIFO最大的特性就是每个FIFO都有一个路径名与之相关联,从而允许无亲缘关系的任意两个进程间通过FIFO进行通信。
int mkfifo(const char * pathname,mode_t mode);
特点
- 使用方式像文件,但不能 seek,你可以通过:
- open()
- read()
- write()
- close()
- 但不能lseek,因为 FIFO 是流式文件,没有偏移量。
- 进入 FIFO 的数据顺序,就是读出的顺序。
- 管道一样,FIFO仅提供半双工的数据通信
open 行为会阻塞
- 打开 FIFO 的读端,如果没有写端打开 → 阻塞
int fd = open("fifo", O_RDONLY); // 没有写端
会阻塞,直到有进程打开写端为止。
- 打开 FIFO 的写端,如果没有读端打开 → 阻塞
int fd = open("fifo", O_WRONLY); // 没有人读
也会阻塞,直到读端出现。
⚠️ 这是命名管道区别于匿名管道的重要特性!!!
匿名管道是在父子进程中自然同时存在读写端,而 FIFO 是“双方需要主动 open”,因此更容易阻塞。
PIPE 与 FIFO 的共同点
- 内核实现层面:本质是同一套机制
- 内核维护的一块 环形缓冲区
- 基于 page cache
- 通过 等待队列 + 锁 实现同步与阻塞
- 都是“流式文件”(Stream)
- 不支持 lseek
- 只能顺序读 / 顺序写
- 都是 FIFO(先进先出)
- 先写入的数据,先被读出
- 没有消息边界(除非你自己定义协议)
共享内存
D-BUS
D-BUS**(Desktop Bus)是一种“消息总线式”的进程间通信(IPC)机制。**用于让不同进程互相通信
特点:
- 多个进程共享一个**“软件总线”**
- 广播消息
- 点对点 :A 进程直接发给 B 进程
System Bus(系统总线) +