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”;
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
參數 值
VPN 0x0E
TLB索引 0x02
TLB标記 0x03
TLB命中 No
缺頁 No
PPN 0x11
11 10 9 8 7 6 5 4 3 2 1 0
0 1 0 0 0 1 1 0 1 0 0 1
參數 值
位元組偏移 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)是不可重入函數,使用全局資料結構