2 编程背景
2.3 程序开发
2.3.1 C 语言变量
- 静态全局变量只对定义它们的文件可见,非静态全局变量对同一程序的所有文件可见。
2.3.2 程序开发步骤
预处理、编译(.s)、汇编(.o)、链接(.out)
.o 文件的组成
- 文件头 + 代码段 + 数据段 + BSS + 重定位信息 + 符号表
链接的主要操作
- 合成各段(代码段、数据段、BSS段)
- 根据重定位信息调整各段偏移量
- 用符号表解析各 .o 文件的交叉引用
2.3.2 静态与动态链接
- 静态:所有库函数都加入 a.out
- 动态:库函数不存入 a.out,a.out 存放调用指令,然后执行期间按需加载
2.3.3 可执行文件格式
- 二进制可执行平面文件:仅包含可执行代码和初始化数据。(比如,可启动操作系统映像(简化了引导装载程序))
- a.out 可执行文件
- ELF 文件
2.3.4 a.out 的内容
- 文件头(各段大小) + 代码段 + 数据段 + 符号表
注意:BSS 段不在 a.out 中,只有 BSS 段的大小记录在 a.out 文件头中
2.3.5 程序终止过程
a. 正常终止
- 清理工作
exit(value)
:刷新 stdout,关闭 I/O 流 - 系统调用
__exit(value)
:- 记录退出状态
- 通知父进程,并使该进程称为僵尸进程
- 父进程 wait 僵尸进程,清空僵尸子进程结构体
b. 异常终止
- 陷入操作系统内核
- 内核的陷入处理程序将陷入错误类型转换成一个幻数(信号)
- 将信号传递给进程,使进程终止
11 EXT2 文件系统
EXT3:增加日志
EXT4:主要变化是磁盘块的分配
11.1 简单的 EXT2 文件系统布局
0 | 1 | 2 | 3-7 | 8 | 9 | 10…32 | 33…1439 |
---|---|---|---|---|---|---|---|
boot(引导块) | super(超级块) | GB(块组描述符) | reserved(保留区) | bmap(块位图) | imap(索引节点位图) | inodes blocks(索引节点块) | data blocks(数据块) |
11.2 超级块结构
1 | struct ext2_super_block { |
- 索引节点数目
- 块数目
- 起始块地址
- 文件块大小
- 已挂载文件系统的次数
- 幻数(标识文件系统类型)
11.3 块组描述符结构
1 | struct ext2_group_desc { |
其中最重要的字段是前三个
11.4 块位图和索引节点位图
11.4.1 块位图 bg_block_bitmap
位图用于表示某种项的位序列,如磁盘块或索引节点。
位图的值 | 描述 |
---|---|
0 | 对应项处于 FREE 状态 |
1 | 对应项处于 IN_USE 状态 |
11.4.2 索引节点位图 bg_inode_bitmap
索引节点位图是用来代表一个文件的数据结构。EXT2 文件系统是使用有限数量的索引节点创建的,各索引节点的状态用索引节点位图的一个位表示。
在 EXT2 文件系统中,前 10 个索引节点是预留的,所以空 EXT2 FS 的 Imap 以 10 个 1 开头,然后是 0。
11.5 索引节点 bg_inode_table
EXT2 每个文件都用一个 128 字节的唯一索引节点结构体表示(EXT4 是 256 字节)
1 | struct ext2_inode { |
i_mode
是 16 位无符号数
i_mode 位 | tttt | ugs | rwx | rwx | rwx |
---|---|---|---|---|---|
描述 | 表示文件类型 tttt=1000表示REG文件 0100表示DIR文件 |
表示文件的特殊用法 | 表示文件权限 | 表示文件权限 | 表示文件权限 |
各时间字段
这些字段都是用自 1970-1-1 00:00:00
开始经过的秒数表示的,所以每个字段都是极大的无符号整数,可以借助库函数char *ctime(&time_field);
将其转为日历形式。
1 | printf("%s", ctime(&inode.i_atime)); |
i_block[15]
包含指向文件磁盘块的指针,如
- 直接块:i_block[0] 至 i_block[11],指向直接磁盘块
- 间接块:i_block[12]
- 双重间接块:i_block[13]
- 三重间接块:i_block[14]
11.6 数据块
紧跟在索引节点块后面的是文件存储数据块,假设有 184 个索引节点,第一个实际数据块是 B33,它就是根目录 /
的i_block[0]。