首页 > 技术文章 > 家庭作业第十章,第九章,第十一章

5320zhq 2015-11-04 20:06 原文

10.8

由于stat函数和fstat函数在功能上很相似,都是检索文件的信息,只是stat函数以文件名作为输入,而fstat函数是以文件描述符作为输入,所以只需把Stat(argv[1],&stat)改为fstat(atoi(argv[1]),&stat)即可实现功能

include “csapp.h”

Int main(int argc,char **argv)
{
struct stat stat;
char type,readok;

fstat(atoi(argv[1]),&stat);
if(S_ISREG(stat.st_mode))
type=”regular”;
else if(S_ISDIR(stat.st_mode))
type=”directory”;
else
type=”other”;
if((stat.st_mode & S_IRUSR))
readok=”yes”;
else
readok=”no”;

printf(“type: %s,read:%s\n”,type,readok);
exit(0);
}

10.9

输入重定向到了foo.txt,然而3这个描述符是不存在的。

说明foo.txt并没有单独的描述符3。

所以Shell执行的代码应该是这样的:

if (Fork() == 0) {/* Child */
int fd = open("foo.txt", O_RDONLY, 0);
dup2(fd, 1);
close(fd);
Execve("fstatcheck", argv, envp);
}

9.11

A.虚拟地址:0x027c

13	12	11	10	9	8	7	6	5	4	3	2	1	0

0	0	0	0	1	0	0	1	1	1	1	1	0	0

B.地址翻译

参数				值

VPN				 0x09

TLB索引		   	0x01

TLB标记			0x02

TLB命中			No

缺页				No

PPN				0x17

C.物理地址格式

11	10	9	8	7	6	5	4	3	2	1	0

0	1	0	1	1	1	1	1	1	1	0	0

D.物理地址引用

参数				值

字节偏移			0x0

缓存索引			0xF

缓存标记			0x17

缓存命中			No

返回缓存字节	  		-

9.12

A.虚拟地址:0x03a9

13	12	11	10	9	8	7	6	5	4	3	2	1	0

0	0	0	0	1	1	1	0	1	0	1	0	0	1

B.地址翻译

参数				值

VPN				0x0E

TLB索引		   0x02

TLB标记		   0x03

TLB命中			No

缺页				No

PPN				0x11

C.物理地址格式

11	10	9	8	7	6	5	4	3	2	1	0

0	1	0	0	0	1	1	0	1	0	0	1

D.物理地址引用

参数				值

字节偏移		  0x1

缓存索引		  0xA

缓存标记		  0x11

缓存命中		   No

返回缓存字节		  -

9.13

A.虚拟地址:0x0040

13	12	11	10	9	8	7	6	5	4	3	2	1	0

0	0	0	0	0	0	0	1	0	0	0	0	0	0

B.地址翻译

参数				值

VPN				0x01

TLB索引		   0x01

TLB标记		   0x00

TLB命中			No

缺页				Yes

PPN				   -

9.15

请求			块大小			块头部

malloc(3)		8			0x9

malloc(11)		16			0x11

malloc(20)		24			0x19

malloc(21)		32			0x21

9.19

1) a; 对于伙伴系统,如果要申请大小为33的空间,那么需要分配64个空间。如果申请大小为65的空间,那么块大小就需要128,所以最多可能有约50%的空间被浪费。b中,最佳适配要搜索所有空间,所以肯定比首次适配要慢一些。c,边界标记主要功能是释放一个块时,能立即和前后空闲块合并。如果空闲块不按顺序排列的话,其实也能够和前一个或者后一个空闲块进行合并,但如果要和前后一起合并,可能会有些困难,那需要搜索前后块在空闲链表中的位置,并且删除一个再进行合并。可以参考P576,LIFO方法。d,其实任何分配器都可能有外部碎片,只要剩余的空闲块大小和足够但是单个都不够,就会产生外部碎片。


2) d; 块大小递增,那么最佳适配法找到的块和首次适配找到的块是同一个,因为最佳适配总是想找一个刚好大于请求块大小的空闲块。a,块大小递减,首次适配很容易找到,所以分配性能会很高。b,最佳适配方法无论怎样,都要搜索所有的链表(除非维护成块大小递增的链表)。c,是匹配的最小的。


3) c; 保守的意思就是所有可能被引用的堆都会被标记,int像指针,所以可能认为它表示的地址是正在被引用的(实际上它只是个int)。

11.9

serve_static中的存储器映射语句改为:

srcfd = open(filename, O_RDONLY, 0);

srcp = (char*)malloc(sizeof(char)*filesize);

rio_readn(srcfd, srcp, filesize);

close(srcfd);

rio_writen(fd, srcp, filesize);

free(srcp);

12.24

可重入函数:当它们被多个线程调用时,不会引用任何共享数据。

满足下面条件之一的多数是不可重入函数:

1.使用了静态数据结构

2.调用了malloc或free

3.调用了标准I/O函数;标准I/O库很多实现都一不可重入的方式使用全局数据结构

4.进行了浮点运算。许多的处理器/编译器中,浮点一般都是不可重入的(浮点运算大多使用协处理器或者软件模拟来实现)

rio_readn(int fd,void *usrbuf,size_t n)是不可重入函数,因为每次调用都共享read(fd,bufp,nleft),使用全局数据结构

rio_writen(int fd,void *usrbuf,size_t n)是不可重入函数, 使用全局数据结构

rio_read(int fd,void *usrbuf,size_t n)是不可重入函数,使用全局数据结构

rio_readlineb(int fd,void *usrbuf,size_t maxlen)是不可重入函数,使用全局数据结构

rio_readnb(int ,void *usrbuf,size_t n)是不可重入函数,使用全局数据结构

推荐阅读