假定第二个进程执行下列代码: 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(已读的总字节数); }