/* 修改main */
Signal(SIGCHLD, handler);
/* 修改serve_dynamic */
去掉Wait(NULL);
void handler(int sig)
{
Wait(NULL);
}
/* Send response body to client */
srcfd = Open(filename, O_RDONLY, 0);
srcp = malloc(filesize);
Rio_readn(srcfd, srcp, filesize);
Close(srcfd);
Rio_writen(fd, srcp, filesize);
free(srcp);
第一题:有误
第二题:正确
#include <csapp.h>
int main()
{
FILE *fp;
pid_t pid = getpid();
long unsigned int start, end;
char filename[30], buffer[200], others[150];
sprintf(filename, "/proc/%d/maps", pid);
fp = fopen(filename, "r"); // 打开/proc/pid/maps 文件
if (fp == NULL)
printf("open file error\n");
while(fgets(buffer, 100, fp) != NULL) //每次读取1行
{
sscanf(buffer, "%lx-%lx %s", &start, &end, others); // 获取每一个区域的开始和结束页号
while(start <= end) //遍历所有页号
{
printf("%lx\n", start++);
}
}
fclose(fp);
return 0;
}
进程对 | 并发地? |
---|---|
AB | 否 |
AC | 是 |
AD | 是 |
BC | 是 |
BD | 是 |
CD | 是 |
ACE
#include <csapp.h>
#define N 2
int main()
{
int status, i;
char *buf = "213";//定义一个字符串常量
pid_t pid;
for (i = 0; i < N; i++)
if ((pid = Fork()) == 0)
{
buf[1] = 'a'; //子进程修改会发生Segmentation fault
}
while((pid = waitpid(-1, &status, 0)) > 0) {
if (WIFSIGNALED(status) && WTERMSIG(status) == 11)
printf("child %d terminated by signal %d: Segmentation fault\n",
pid, WTERMSIG(status));
else
printf("child %d terminated abnormally\n", pid);
}
if (errno != ECHILD)
unix_error("waitpid error");
exit(0);
}
fd2 = 4
if (argv[2] == '<')
{
int fd = Open(argv[3], O_RDONLY, 0);
Dup2(fd, argv[1]);
}
第一题:正确
第二题:正确
第三题:有误
第四题:正确
第五题:有误
符号 | swap.o.symtab条目? | 符号类型 | 定义符号的模块 | 节 |
---|---|---|---|---|
buf | 有 | 外部 | m.o | .data |
buf0 | 有 | 全局 | swap.o | .data |
buf1 | 有 | 局部 | swap.o | .bss |
swap | 有 | 全局 | swap.o | .text |
temp | 无 | —— | —— | —— |
incr | 有 | 局部 | swap.o | .text |
count | 有 | 局部 | swap.o | .bss |
/* bar5.c */
int x;
void f()
{
}
refaddr = ADDR(.text) + r.offset
= 0x4004e0 + 0xa
= 0x4004ea
*refptr = (unsigned)(ADDR(swap) + r.addend - refaddr)
= (unsigned)(0x4004f8 + 0x-4 - 0x4004ea)
= (unsigned)(0xa)
refaddr = ADDR(.text) + r.offset
= 0x4004d0 + 0xa
= 0x4004da
*refptr = (unsigned)(ADDR(swap) + r.addend - refaddr)
= (unsigned)(0x400500 + 0x-4 - 0x4004da)
= (unsigned)(0x22)
libc.a : 1579 libm.a : 471
不同
linux-vdso.so.1
libc.so.6
ld-linux-x86-64.so.2
第一题:有一处错误
第二题:正确
第三题:正确
第四题:正确
!(~x)
!x
!(~(0xFFFFFF00 | x))
!(x & 0xFF000000)
int int_shifts_are_arithmetic()
{
return !(~(-1 >> ( 8 * sizeof(int)));
}
int odd_ones(unsigned x)
{
x ^= ( x >> 16 );
x ^= ( x >> 8 );
x ^= ( x >> 4 );
x ^= ( x >> 2 );
x ^= ( x >> 1 );
return x & 1;
}
第一题:正确(C、D有点小问题)
第二题:有误
第三题:正确
float_bits float_negate(float_bits f)
{
unsigned sign = f & 0x80000000;
unsigned exp = f & 0x7f800000;
unsigned frac = f & 0x7fffff;
if (exp == 0x7f800000 && frac == 0)
return f;
else
{
sign ^= 0x80000000;
f = sign | exp | frac;
}
return f;
}
int float_f2i(float_bits f)
{
int res, shift;
unsigned h;
memcpy(&h, &f, 4);
unsigned sign = h & 0x80000000;
unsigned exp = (h & 0x7f800000) >> 23;
unsigned frac = h & 0x7fffff;
if (exp > 159)
res = 0x80000000;
else if (exp <= 126)
res = 0;
else if (exp != 159)
{
shift = exp - 150;
frac |= 0x800000;
if (shift > 0)
frac <<= shift;
else
frac >>= -shift;
if (sign == 0x0)
res = frac;
else
res = ~frac + 1;
}
return res;
}
第一题:有2个错误 第二题:有误 第三题:有误
long loop(long x, int n)
{
long result = 0;
long mask;
for(mask = 1; mask != 0; mask = mask << n)
result |= x & mask;
return result;
}
x : %rdi
n : %esi
result : %rax
mask : %rdx
result = 0; mask = 1;
mask != 0;
mask <<= n;
result |= x & mask;
long switch(long *p1, long *p2, mode_t action)
{
long result = 0;
switch(action){
case MODE_A:
result = *p2;
*p2 = *p1;
break;
case MODE_B:
result = *p1 + *p2;
*p1 = result;
break;
case MODE_C:
*p1 = 59;
result = *p2;
break;
case MODE_D:
*p1 = *p2;
result = 27;
break;
default:
result = 12;
}
return result;
}
&A[i][j][k] = XA + 8 * (i * S * T + j * T + k);
R = 7 S = 5 T = 13
第一题:正确
第二题:MODE_E呢?
第三题:正确
A = 9; B = 5;
A:CNT = 7;
B:
typedef struct{
long idx;
long x[4];
}a_struct;
A:0 8 0 8
B:16
C:
up->e1.p = *(up->e2.next->p) - up->e2.next->y
第一题:正确
第二题:正确
第三题:正确
/* Bubble sort: Array version */
void buble_a(long *data, long count)
{
long i, last;
for (last = count - 1; last > 0; last--)
{
for (i = 0; i < last; i++)
if (*(data + i + 1) < *(data + i))
{
long t = *(data + i + 1);
*(data + i + 1) = *(data + i);
*(data + i) = t;
}
}
}
.pos 0
init:
irmovl Stack, %esp
irmovl Stack, %ebp
call Main
halt
#测试数据
.align 4
data:
.long 0x09
.long 0x01
.long 0x03
.long 0x05
.long 0x08
.long 0x0e
.long 0x1a
.long 0x2f
.long 0xff
.long 0xaa
Main:
pushl %ebp
rrmovl %esp, %ebp
irmovl data, %edi
irmovl $0xa, %esi
call bubble
rrmovl %ebp, %esp
popl %ebp
ret
bubble:
irmovl $1, %ecx
subl %ecx, %esi # last in esi
jmp test1
loop1:
xorl %edx, %edx #i in edx
jmp test2
loop2:
rrmovl %edx, %eax
addl %eax, %eax #eax = 2 * i
addl %eax, %eax #eax = 4 * i
addl %edi, %eax #eax = data + 4 * i
mrmovl 4(%eax), %ebx
mrmovl (%eax), %ecx
pushl %eax
rrmovl %ebx, %eax
subl %ecx, %eax
jg L
popl %eax
rmmovl %ecx, 4(%eax)
rmmovl %ebx, (%eax)
L:
irmovl $1, %ecx
addl %ecx, %edx
test2:
rrmovl %esi, %ebx
subl %edx, %ebx
jg loop2
irmovl $1, %ecx
subl %ecx, %esi
test1:
andl %esi, %esi
jg loop1
ret
.pos 0x100
Stack:
## What address should instruction be fetched at
int f_pc = [
# Mispredicted branch. Fetch at incremented PC
M_icode == IJXX && M_ifun != UNCOND && M_valE < M_valA && !M_Cnd : M_valA;
M_icode == IJXX && M_ifun != UNCOND && M_valE >= M_valA && M_Cnd : M_valE;
# Completion of RET instruction.
W_icode == IRET : W_valM;
# Default: Use predicted value of PC
1 : F_predPC;
];
# Predict next value of PC
int f_predPC = [
# BBTFNT: This is where you'll change the branch prediction rule
f_icode in { ICALL }
|| f_icode == IJXX && (f_ifun == UNCOND || f_ifun != UNCOND && f_valC < f_valP) : f_valC;
1 : f_valP;
];
## Select input A to ALU
int aluA = [
E_icode in { IRRMOVL, IOPL } : E_valA;
E_icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX } : E_valC;
E_icode in { ICALL, IPUSHL } : -4;
E_icode in { IRET, IPOPL } : 4;
# Other instructions don't need ALU
];
## Select input B to ALU
int aluB = [
E_icode in { IRMMOVL, IMRMOVL, IOPL, ICALL,
IPUSHL, IRET, IPOPL } : E_valB;
E_icode in { IRRMOVL, IIRMOVL } : 0;
# Other instructions don't need ALU
];
bool D_bubble =
# Mispredicted branch
E_icode == IJXX && (E_ifun != UNCOND && (E_valC < E_valA && !e_Cnd || E_valC >= E_valA && e_Cnd)) ||
# BBTFNT: This condition will change
# Stalling at fetch while ret passes through pipeline
# but not condition for a load/use hazard
!(E_icode in { IMRMOVL, IPOPL } && E_dstM in { d_srcA, d_srcB }) &&
IRET in { D_icode, E_icode, M_icode };
bool E_bubble =
# Mispredicted branch
E_icode == IJXX && (E_ifun != UNCOND && (E_valC < E_valA && !e_Cnd || E_valC >= E_valA && e_Cnd)) ||
# BBTFNT: This condition will change
# Conditions for a load/use hazard
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB};
B:3.00
C:1.00
D:乘法操作不会构成数据相关,并不是制约性能的关键路径
void inner4(vec_ptr u, vec_ptr v, data_t *dest)
{
long i;
long length = vec_length(u);
data_t *udata = get_vec_start(u);
data_t *vdata = get_vec_start(v);
data_t sum = (data_t) 0;
long limit = length - 5;
for (i = 0; i < limit; i += 6)
{
sum = sum + udata[i] * vdata[i]
+ udata[i + 1] * vdata[i + 1]
+ udata[i + 2] * vdata[i + 2]
+ udata[i + 3] * vdata[i + 3]
+ udata[i + 4] * vdata[i + 4]
+ udata[i + 5] * vdata[i + 5];
}
for (; i < length; i++)
{
sum = sum + udata[i] * vdata[i];
}
*dest = sum;
}
内积计算每次需要加载两个数据,,处理器只有两个加载单元,每个周期最多只能读取两次数值,因此吞吐量界限是1.00
对于浮点数的cpe等于3.00,已经达到了浮点数加法的延迟界限,不能再提高
第一题:正确
第二题:正确
第三题:正确
第四题:正确