《操作系统》文件读写讨论题

讨论题 4.22 采用“文件目录分解法”,每个盘块为 512 字节,分解前每个目录占 64 字节,其中文件名占 8 字节。 分解后,第一部分占 10 字节(包括文件名和文件内部号), 第二部分占 56 字节(包括文件内部号和文件其他描述信息),文件内部号为 2 字节。
(1)假设某一目录文件共有 254 个文件控制块,试分别给出采用分解法前和分解法后,查找该目录中某个文件控制块的平均访问磁盘次数。
(2)一般情况, 若目录文件分解前占用 n 个盘块, 分解后改用 m 个盘块存放文件名
和文件内部号部分, 请给出访问磁盘次数减少的条件。

(1) 分解前:最少访问1次,最多访问32次,平均访问16.5次
分解后:最少访问2次,最后访问6次,平均访问4次
(2) 分解前平均访问(n + 1 )/2,分解后平均访问(m + 3) / 2,所以m 要小于 n-2

4.52 写出 Linux 环境下,获取/home/can/hello 文件基本目录的过程。

1、从分区的根目录/目录表中查到home得到i节点号x;
2、读取i节点区第x项内容 ,从中得到/home内容盘块号a;
3、读取a号磁盘块到内存得到/home目录表,搜索/home目录得到can的i节点号y;
4、读取i节点第y项内容,得到/home/can内容盘块号为b;
5、读取b号磁盘块到内存得到/home/can目录表。搜索/home/can目录得到/hello的i节点号z
6、最后,读取i节点第z项内容获取/home/can/hello 文件基本目录。
在这里插入图片描述

4.53 操作系统的文件管理模块有哪几种提高文件搜索效率的措施?

1、采用分解式目录管理、,分为符号目录项和基本目录项,减少读盘次数
2、为进程设置一个当前目录、并将改目录的内容读入到内存

4.54考虑读文件系统调用"read(fd, buf, len);“的实现。假设当前文件读写指针位置为 pos, 逻辑数据块和磁盘块大小都是 BSIZE,
(1)计算要读入的第 1 个字节和最后一个字节距文件起始位置的字节距离。
(2)计算需读几个数据块,给出其逻辑块号的范围。
(3)假设已有将文件 fd 中逻辑块号为 n 的数据块读入内存缓冲区 rec 的库函数"int ReadLBlock(int fd,int n, void * rec);”,其中返回值是实际读出字节数。请写出实现函数"int read(fd,void *buf,size_t len);"的实现程序。

(1) 要读入的第一个字节距文件起始位置的字节距离为 pos, 要读入的最后一个字节距文件起始位置的字节距离为 pos+len-1

(2)数据块的数量: ⌊ p o s + l e n − 1 B S I Z E ⌋ − ⌊ p o s B S I Z E ⌋ + 1 \lfloor\frac{pos+len-1}{BSIZE} \rfloor - \lfloor\frac{pos}{BSIZE} \rfloor + 1 BSIZEpos+len1BSIZEpos+1
范围: ⌊ p o s B S I Z E ⌋ − 到 − ⌊ p o s + l e n − 1 B S I Z E ⌋ \lfloor\frac{pos}{BSIZE} \rfloor -到- \lfloor\frac{pos+len-1}{BSIZE} \rfloor BSIZEposBSIZEpos+len1

(3)

int read(fd,void *buf,size_t len) {
    
    
	int block_start, block_end;
	off_set pos;
	pos = lseek(fd, 0, SEEK_CUR); //get current position
	block_start = pos / BSIZE;
	block_end = (pos + len)/BSIZE;
	char *block_buf = malloc(BSIZE) * (block_end - block_start + 1); 		//prepare buffer
 	for (i = block_start; i <= block_end; i++){
    
    
 		ReadBlock(fd,i, block_buf + (i-block_start) * BSIZE]);
	}
	off_set offset_start = pos % BSIZE;
	memcpy(block_buf + offset_start, buf, len); //copy data from block buf to buffer
	 return len;
}

4.55考虑读文件系统调用"write(fd, buf, len);",假设当前文件读写指针位置为 pos,磁盘块大小为 BSIZE,
(1)计算要写入的首字节和末字节距文件起始位置的字节距离。
(2)计算要读写几个数据块,给出其逻辑块号的范围。
(3)假设将文件 fd 中块号为 n 某个数据块读入内存缓冲区 rec 的库函数为"intReadLBlock(int fd,int n, char rec[BSIZE]);",其中返回值是实际读出字节数;而将内存缓冲区 rec 内容写入某个数据块 n 写入文件 fd 的库函数为 WriteLBlock(int fd,int n, char rec[BSIZE]);"。 请写出实现函数"int write(fd,void *buf,size_t len);"的实现程序。

(1) 要读入的第一个字节距文件起始位置的字节距离为 pos, 要读入的最后一个字节距文件起始位置的字节距离为 pos+len-1
(2)数据块的数量: ⌊ p o s + l e n − 1 B S I Z E ⌋ − ⌊ p o s B S I Z E ⌋ + 1 \lfloor\frac{pos+len-1}{BSIZE} \rfloor - \lfloor\frac{pos}{BSIZE} \rfloor + 1 BSIZEpos+len1BSIZEpos+1
范围: ⌊ p o s B S I Z E ⌋ − 到 − ⌊ p o s + l e n − 1 B S I Z E ⌋ \lfloor\frac{pos}{BSIZE} \rfloor -到- \lfloor\frac{pos+len-1}{BSIZE} \rfloor BSIZEposBSIZEpos+len1

int write(fd,void *buf,size_t len) {
    
    
    int block_start, block_end;
    off_set pos;
    pos = lseek(fd, 0, SEEK_CUR); //get current position
    block_start = pos / BSIZE;
    block_end = (pos + len)/BSIZE;
    block_start_offset = pos % BSIZE; //if 0, no need to read the block
    block_end_offset = (pos+len) % BSIZE; //if =0, noeed to read the block
    char *block_buf = malloc(BSIZE) * (block_end - block_start + 1); //prepare buffer
    //save the first and last block if required
    if(block_start_offset!=0)
    ReadBlock(fd, block_start, block_buf + (i-block_start) * BSIZE]);
    if(block_end_offset!=0)
    ReadBlock(fd, block_end, block_buf + (block_end-block_start) * BSIZE]); //copy data from block buf to buffer
    off_set offset_start = pos % BSIZE;
    memcpy(block_buf + offset_start, buf, len); 		 //write to disk
    for (i = block_start; i <= block_end; i++){
    
    
		write(fd,i, block_buf + (i-block_start) * BSIZE]);
    }
    return len;
}

猜你喜欢

转载自blog.csdn.net/weixin_51233575/article/details/123911270
今日推荐