/*在main函数前增加一个函数*/
int childEnded;
void signal_handler(int sig)
{
pid_t pid;
while((pid = waitpid(-1, NULL, WNOHANG)) > 0)
;
childEnded = 1;
}
/*在main函数中加入signal(SIGCHILD, signal_handler);*/
/*每次accept之前要将childEnded置0;*/
/*在doit()中的serve_dynamic之后添加:*/
/*while(!childEnded) pause(); 若子进程未终结,则中止程序*/
/*最后还需删掉serve_dynamic里的wait(NULL);*/
/* Changed code */
/* Send response body to client */
srcfd = Open(filename, O_RDONLY, 0);
rcp = (char*)malloc(sizeof(char)*filesize);
Rio_readn(srcfd, srcp, filesize);
Close(srcfd);
Rio_writen(fd, srcp, filesize);
Free(srcp);
第一题:有误(另外,while()pause()是不安全的)
第二题:scrp?rcp
#include<stdio.h>
#include<signal.h>
#include"csapp.h"
#include<setjmp.h>
sigjmp_buf buf;
char *a= (char*)(long)(0x400000);//虚拟地址起始地址
char *b= (char*)(long)(0x0);
void handler(int sig)
{
siglongjmp(buf,1);
}
int main()
{
signal(SIGSEGV,handler);
while((long)a <= (((long)1)<<32))
{
if(sigsetjmp(buf,1))//有错误,不能访问该虚拟页
{
a+=4096;//1页大小为4k
continue;
}
else
{
char tmp = *a;//访问该虚拟页
printf("VPN: %ld \n",(a-b)/4096);//打印页号
a+=4096;
}
}
return 0;
}
64位地址,只打印了低32位地址
进程对 | 并发地? |
---|---|
AB | F |
AC | T |
AD | T |
BC | T |
BD | T |
CD | T |
ACE
#include "csapp.h"
#define N 2
int main()
{
int status, i;
pid_t pid;
char errorInfo[128];
/* Parent creates N children */
for(i=0;i<N;i++)
if ((pid = Fork()) == 0) /* Child */
exit(100+i);
/* Parent reaps N children in no particular order */
while ((pid = waitpid(-1, &status, 0)) > 0) {
if (WIFEXITED(status))
printf("child %d terminated normally with exit status=%d\n",
pid, WEXITSTATUS(status));
else if(WIFSIGNALED(status))
{
printf("child %d terminated by signal %d: ", pid, WTERMSIG(status) );
psignal(WTERMSIG(status), errorInfo);
}
}
/* The only normal termination is if there are no more children */
if (errno != ECHILD)
unix_error("waitpid error");
exit(0);
}
fd2 = 4
if (Fork() == 0) { /* Child */
/* The Shell may be run these code? */
fd = Open("foo.txt", O_RDONLY, 0); /打开foo.txt fd=3
dup2(fd, STDIN_FILENO); //重定向
close(fd);
Execve("fstatcheck", argv, envp);
}
第一题:正确
第二题:正确
第三题:错误
第四题:正确
第五题:正确
符号 | swap.o .symtab 条目? | 符号类型 | 定义符号的模块 | 节 |
---|---|---|---|---|
buf | Y | extern | m.o | .data |
bufp0 | Y | global | swap.o | .data |
bufp1 | Y | local | swap.o | .bss |
swap | Y | global | swap.o | .text |
temp | N | --- | --- | --- |
incr | Y | local | swap.o | .text |
count | Y | local | swap.o | .bss |
/* bar5.c */
static double x;
void f()
{
x = -0.0;
}
A.
0x4004f8-4-(0x4004e0+0xa)=0xa
B.
0x400500-4-(0x4004d0+0xa)=0x22
A. lib.c 1579 libm.a 471
B. 运行了一个hello world,-g 版本多了debug部分
C. linux-vdso.so.1 libc.so.6
第一题:有一处错误
第二题:正确
第三题:正确
第四题:正确
A.
void bubble(long *data, long count) {
if(count == 0) return;
long i, j;
long *p, *q;
for(i=count-1; i!=0; i--){
p = data, q = data + 1;
for(j=0; j!=i; ++j) {
if( *p > *q ) {
long t = *p;
*p = *q;
*q = t;
}
p++;
q++;
}
}
}
B.
# Execution begins at address 0
.pos 0
init:
irmovl Stack, %esp # Set up stack pointer
irmovl Stack, %ebp # Set up base pointer
call main # Execute main program
halt # Terminate program
.align 4
# data block
src:
.long 0x8
.long 0x2
.long 0x4
.long 0x7
.long 0x1
.long 0x3
.long 0x5
.long 0x6
main:
irmovl $8, %ecx
pushl %ecx #count = 8
irmovl src, %ecx
pushl %ecx #push data
call bubble
halt
# void bubble(long *data, long count)
bubble:
pushl %ebp
rrmovl %esp, %ebp
pushl %esi
pushl %ebx
pushl %edx
mrmovl 8(%ebp), %edx #edx == data
mrmovl 12(%ebp), %esi #esi == count
andl %esi, %esi
je bubbleEnd #count==0
irmovl $1, %eax
subl %eax, %esi #count--
je bubbleEnd #count==1
Loop1:
rrmovl %edx, %ecx # p = data (ecx)
pushl %esi # to save one reg
Loop2:
mrmovl (%ecx), %eax
mrmovl 4(%ecx), %ebx
subl %eax, %ebx
mrmovl 4(%ecx), %ebx
jg NoSwap
rrmovl %eax, %ebx #swap
mrmovl 4(%ecx), %eax
NoSwap:
rmmovl %eax, (%ecx)
rmmovl %ebx, 4(%ecx)
irmovl $4, %eax
addl %eax, %ecx
irmovl $1, %eax
subl %eax, %esi
jne Loop2
popl %esi
irmovl $1, %eax
subl %eax, %esi
jne Loop1
bubbleEnd:
popl %edx
popl %ebx
popl %esi
rrmovl %ebp, %esp
popl %ebp
ret
# The stack starts here and grows to lower addresses
.pos 0x100
Stack:
Here are the changes:
## What address should instruction be fetched at
int f_pc = [
# Mispredicted forward
M_icode == IJXX && M_ifun != UNCOND && M_Cnd && M_valE >= M_valA: M_valE;
# Mispredicted backward
M_icode == IJXX && M_ifun != UNCOND && !M_Cnd && M_valE < M_valA: M_valA;
# 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 == IJXX && f_ifun != UNCOND && f_valC < f_valP : f_valC;
f_icode == IJXX && f_ifun == UNCOND : f_valC;
f_icode == ICALL : f_valC;
1 : f_valP;
];
# BBTFNT: When some branches are predicted as not-taken, you need some
# way to get valC into pipeline register M, so that
# you can correct for a mispredicted branch.
## 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, IJXX} : 0;
# Other instructions don't need ALU
];
bool D_bubble =
# Mispredicted branch
(E_icode == IJXX && E_ifun != UNCOND && e_Cnd && e_valE >= E_valA) ||
(E_icode == IJXX && E_ifun != UNCOND && !e_Cnd && e_valE < E_valA) ||
# 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 };
# Should I stall or inject a bubble into Pipeline Register E?
# At most one of these can be true.
bool E_stall = 0;
bool E_bubble =
# Mispredicted branch
(E_icode == IJXX && E_ifun != UNCOND && e_Cnd && e_valE >= E_valA) ||
(E_icode == IJXX && E_ifun != UNCOND && !e_Cnd && e_valE < E_valA) ||
# BBTFNT: This condition will change
# Conditions for a load/use hazard
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB};
A.图片发给助教
B.
浮点型数据add的延迟 3.00
C.
整型数据add的延迟 1.00
D. 因为浮点乘法的发射周期为1,是完全流水线化的,可以提前、连续地发射乘法运算;而浮点加法在关键路径中,故从CPE的下界由浮点加法的延迟决定
A.
Intal Core i7 Haswell 只有两个加载单元,由5.13.A的关键路径可得每个周期都要加载2个值(u和v的值),故CPE下界不能低于吞吐量下界1.00
B.
kx1 循环展开后,关键路径还是有n个add操作,且使用同一个寄存器来保存,而浮点add延迟为3.00,故CPE下界并不会降低。
第一题:正确
第二题:正确
第三题:正确
第四题:代码呢??
A=9
B=5
A. CNT=7
B.
a_struct{
long idx;
long x[4];
}
A
e1.p 0
e1.y 8
e2.x 0
e2.next 8
B 16
C
void proc (union ele *up){
up->e2.x = *(up->e2.next->e1.p)-up->e2.next->e2.y;
}
第一题:正确
第二题:正确
第三题:正确
A.%rdi %esi %rax %rdx
B.0 1
C.mask!=0
D.mask<<(n%256)
E.mask&x
F.
long loop(long x,int n)
{
long result = 0;
long mask;
for(mask = 1; mask !=0; mask=mask <<(n%256))
{
result |= mask & x;
}
return result;
}
long switch3(long *p1, long *p2, mode_t action)
{
long result =0;
switch(action){
case MODE_A:{
result = *p2;
action = (made_t) *p1;
*p2 = action;
break;
}
case MODE_B:{
result = *p1;
result += *p2;
*p1 =result ;
break;
}
case MODE_C:{
*p1 = 59;
result = *p2;
break;
}
case MODE_D:{
result = *p2;
*p1 = result;
result = 27;
break;
}
case MODE_E:{
result = 27;
break;
}
defult:{
result = 12;
return result;
}
}
return result;
}
A. A[i][j][k]=A+l*(iST+j*T+k) (A是数组初始地址,l是单位元素的地址长度)
B. R=7 S=5 T=13
第一题:正确
第二题:正确
第三题:正确
A | bits | value |
---|---|---|
208 | 011101010 | 208 |
-7/1024 | 100010111 | -7/1024 |
5/131072 | 000000001 | 1/1024 |
-1/4096 | 111101111 | -248 |
768 | 01111 0000 | +∞ |
float_bits float_negate(float_bits f)
{
int exp=(f>>23)&0xff;
int frac=f&0x7fffff;
if(!(exp^0xff)&&(frac!=0))
return f;
return (1<<31)^f;
}
int float_f2i(float_bits f)
{
int sign=(f>>31)&1;
int exp=(f>>23)&0xff-127;
int frac=f&0x7fffff+0x800000;
if(exp<0) return 0;
if(exp>=31)
{
return 0x80000000;
}
if(exp>=23)
{
if(sign) return -(frac<<(exp-23));
else return frac<<(exp-23);
}
else
{
if(sign) return -(frac>>(23-exp));
else return frac>>(23-exp);
}
}
第一题:有1个错误
第二题:正确
第三题:正确
!(x+1)||!x||!((x^0xff)&0xff)||!(x>>((sizeof(int)<<3)-8))
int_shifts_are_arithmetic()
{
return(!(((~0)>>((sizeof(int)<<3)-1))+1));
}
int odd_ones(unsigned x)
{
x=(x>>16)^x;
x=(x>>8)^x;
x=(x>>4)^x;
x=(x>>2)^x;
x=(x>>1)^x;
return x&1;
}
第一题:正确
第二题:正确
第三题:正确