第五章 文件系统的系统调用 本章主要介绍针对上层用户使用的系统调用。用户通 过使用本章介绍的系统调用来申请操作系统中有关文件和 文件系统操作的各项功能。 本章介绍的算法是基于第四章所介绍的底层文件系统算 法之上的,主要包括七大类操作: 返回文件描述符类操作 路径名转换类操作 分配索引节点类操作 文件属性类操作 文件输入输出类操作 文件系统装卸类操作 文件系统目录树操作 1
第五章 文件系统的系统调用 本章主要介绍针对上层用户使用的系统调用。用户通 过使用本章介绍的系统调用来申请操作系统中有关文件和 文件系统操作的各项功能。 本章介绍的算法是基于第四章所介绍的底层文件系统算 法之上的,主要包括七大类操作: 返回文件描述符类操作 路径名转换类操作 分配索引节点类操作 文件属性类操作 文件输入输出类操作 文件系统装卸类操作 文件系统目录树操作 1
系统调用 返回文件描述符 使用namei 分配索引节点 文件属性 文件I/0 文件系统结构 目录树操作 open dup open stat creat creat chown read mount chdir creat pipe link chdir unlink mknod chmod write umount chroot close chroot mknod chown link stat stat mount chmod umount unlink 底层文件系统算法 namei ialloc ifree alloc free bmap iget iput 缓冲区分配算法 getblk brelse bread breada bwrite 2
系 统 调 用 返回文件描述符 使用namei 分配索引节点 文件属性 文件I/O 文件系统结构 目录树操作 open dup open stat creat creat chown read mount chdir creat pipe link chdir unlink mknod chmod write umount chroot close chroot mknod chown link stat stat mount chmod umount unlink 2 底层文件系统算法 namei ialloc ifree alloc free bmap iget iput 缓冲区分配算法 getblk brelse bread breada bwrite
1、算法open 输入:文件名 打开文件类型 文件许可权方式(对以创建方式打开而言) 输出:文件描述符 { 将文件名转换为索引节点(算法namei); f(文件不存在或不允许存取) return(错); 为索引节点分配系统打开文件表项,设置引用计数和偏移量; 分配用户文件描述符表项,将指针指向系统打开文件表项; f(打开的类型规定清除文件) 释放占用的所有文件系统块(算法free); 解锁(索引节点);:在上面的namei算法中上了锁*/ return(用户文件描述符); } 3
3 1、算法 open 输入:文件名 打开文件类型 文件许可权方式(对以创建方式打开而言) 输出:文件描述符 { 将文件名转换为索引节点(算法namei); if (文件不存在或不允许存取) return (错); 为索引节点分配系统打开文件表项,设置引用计数和偏移量; 分配用户文件描述符表项,将指针指向系统打开文件表项; if (打开的类型规定清除文件) 释放占用的所有文件系统块(算法free); 解锁(索引节点); /* 在上面的namei算法中上了锁 */ return(用户文件描述符); }
假定一个进程执行下列代码: fd1=open("/etc/passwd",ORDONLY) fd2=open("local",O WRONLY); fd3=open("/etc/passwd",O RDWR) 下图为打开文件后的数据结构: 4
假定一个进程执行下列代码: fd1=open(“/etc/passwd”,O_RDONLY); fd2=open(“local”,O_WRONLY); fd3=open(“/etc/passwd”,O_RDWR); 下图为打开文件后的数据结构: 4
用户文件描述符表 系统打开文件表 活动inode表 0 1 23 4567 引用数1 只读 引用数2 letc/passwd 引用数1 读写 引用数1 local 引用数1 只写 5
5 . . . . . 用户文件描述符表 0 1 2 3 4 5 6 7 . . . . . 系统打开文件表 活动 inode表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 引用数 1 只读 引用数 1 读写 引用数 1 只写 引用数2 /etc/passwd 引用数1 local
假定第二个进程执行下列代码: fdl=open(“/etc/passwd”,O RDONLY); fd2=open(“private”,O RDONLY); 则相关的数据结构如下: 6
6 假定第二个进程执行下列代码: fd1 = open(“/etc/passwd”, O_RDONLY); fd2 = open(“private”, O_RDONLY); 则相关的数据结构如下:
用户文件描述符表 系统打开文件表 活动inode:表 0 1 3 4 5 引用数1 只读 引用数3 letc/passwd A进程 引用数1 读写 01 引用数1 local 234 引用数1 只读 5 引用数1 只写 引用数1 private B进程 引用数1 只读
7 . . . . . 用户文件描述符表 0 1 2 3 4 5 . . . . . 系统打开文件表 活动 inode表 . . . . . . . . . . . . . . . . . . . . . . . . . . . 引用数 1 只读 引用数 1 读写 引用数 1 只写 引用数3 /etc/passwd 引用数1 local . . . . . 0 1 2 3 4 5 A进程 B进程 引用数 1 只读 引用数 1 只读 . . . . . . . . . . . . 引用数1 private
2、算法read 系统调用read的语法格式如下: number read (fd,buffer,count); fd是由open返回的文件描述符 buffer是用户进程中的用于保存数据的缓冲区地址 count是用户要读的字节数 number是实际读出的字节数 在u区中保存的I/0参数为 方式 指示读或写 计数 读或写的字节数 偏移量文件中的字节偏移量 地址 拷贝数据的目的地址,在用户或核心存储器中 标志 指出地址是在用户空间还是核心空间 8
8 2、算法 read 系统调用read的语法格式如下: number = read (fd, buffer, count); fd 是由open返回的文件描述符 buffer 是用户进程中的用于保存数据的缓冲区地址 count 是用户要读的字节数 number 是实际读出的字节数 在u区中保存的I/O参数为 方式 指示读或写 计数 读或写的字节数 偏移量 文件中的字节偏移量 地址 拷贝数据的目的地址,在用户或核心存储器中 标志 指出地址是在用户空间还是核心空间
算法read 输入:用户文件描述符 用户进程中的缓冲区地址 要读的字节数 输出:拷贝到用户区的字节数 { 由用户文件描述符得到系统打开文件表项(file表项); 检查文件的可存取性; 在u区中设置用户地址、字节计数、输入/输出到用户的参数: 从file表项找到索引节点; 索引节点上锁; 用file表项中的偏移量设置u区中的字节偏移量; (接下页) 9
9 算法 read 输入:用户文件描述符 用户进程中的缓冲区地址 要读的字节数 输出:拷贝到用户区的字节数 { 由用户文件描述符得到系统打开文件表项(file表项); 检查文件的可存取性; 在u区中设置用户地址、字节计数、输入/输出到用户的参数; 从file表项找到索引节点; 索引节点上锁; 用file表项中的偏移量设置u区中的字节偏移量; (接下页)
while(要读的字节数还不满足) f 将文件偏移量转换为文件系统块号((算法bmap); 计算块中的偏移量和要读的字节数; f(要读的字节数为0) 体企图读文件尾*/ break; *退出循环*/ 读文件块(如果要预读,用breada,否则用bread); 将数据从系统缓冲区拷贝到用户地址; 修改u区中的字节偏移量、读计数、再写的用户空间地址; 释放缓冲区; /*在bread中上了锁*/ } 解锁索引节点: 修改le表中的偏移量,用作下次读操作; return(已读的总字节数); } 10
10 while (要读的字节数还不满足) { 将文件偏移量转换为文件系统块号(算法bmap); 计算块中的偏移量和要读的字节数; if (要读的字节数为0) /* 企图读文件尾 */ break; /* 退出循环 */ 读文件块(如果要预读,用breada,否则用bread); 将数据从系统缓冲区拷贝到用户地址; 修改u区中的字节偏移量、读计数、再写的用户空间地址; 释放缓冲区; /* 在bread中上了锁 */ } 解锁索引节点; 修改file表中的偏移量,用作下次读操作; return(已读的总字节数); }