第一题:7.12
答:
行号 | 地址 | 值 |
15 | 0x80483cb | 0x804945c |
16 | 0x80483d0 | 0x8049458 |
18 | 0x80483d8 | 0x8049548 |
18 | 0x80483dc | 0x8049458 |
23 | 0x80483e7 | 0x8049548 |
第二题:7.13
答:A. 链接器将修改.text中的call 12 <p1+0xa>,mov 0x0,%eax,call 21 <p1+0x19>这三条指令。
具体的重定位条目信息如下:
节偏移 | 重定位类型 | 符号 |
00000012 | R_386_PC32 | p3 |
00000019 | R_386_32 | xp |
00000021 | R_386_PC32 | p2 |
B. 链接器将修改.data节中的xp这一数据目标。
具体的重定位条目信息如下:
节偏移 | 重定位类型 | 符号 |
00000004 | R_386_32 | x |
第三题:7.15
答:A. 如下图所示,在我的系统上,libc.a中包含1599个目标文件,libm.a中包含428个目标文件。
B. 无论程序是否使用 -g编译,.text部分中的代码都是相同的。不同之处在于,“-O2 -g”对象文件在 .debug部分包含调试信息,而 “-O2” 版本则没有。
C. 如下图所示,在我的系统上,gcc驱动程序使用标准的C库 (libc.so.6)和动态链接器 (ld-linux.so.2) :
第四题:8.19
答:此函数第一次循环后共两个进程,第二次循环后共4个进程,第三次循环后共8个进程,以此类推,第n次循环后共2n个进程。
即此函数共调用fork函数2n -1次,最终共2n个进程。父级和每个子级打印一行输出,总共2n行输出。
第五题:8.21
答:如果父进程先运行,它会先输出 “b” ,然后等待子进程运行结束。当子进程输出 “a” 并退出后,父进程从 waitpid 返回继续执行,输出 “c” 后退出。此时的输出序列为 “bac”。
如果子进程先运行,它会先输出 “a” 并退出。然后父进程运行,输出 “b” 后调用 waitpid 等待子进程,由于子进程此时已经结束了,所以父进程会直接获取子进程的退出状态并从 waitpid 返回继续执行,输出 “c” 然后退出。此时的输出序列为 “abc”。
综上,该程序只有两个可能的输出序列:“abc” 或 “bac”。
第六题:8.23
答:信号不能用于计数其他进程中的事件,因为信号没有排队。
在测试程序中,子进程很快地连续发送五个 SIGUSR2 信号到父进程,但如果信号处理器还在处理前一个信号,与正在处理的信号相同类型的待处理信号会被阻塞,后续的同类型信号不会排队等待处理,而是简单地丢失,从而会导致错误。
解决这个问题可以使用进程间通信(IPC)机制或线程等。