/*在serve_dynamic()的开头加上这一行*/
Signal(SIGCHLD,sigchld_handler);
/*增加一个handler函数*/
void sigchld_handler(int sig)
{
while(waitpid(-1,0,WNOHANG)>0);
return;
}
修改serve_static()中的部分代码
/*Send response body to client*/
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);
第一题:有误
第二题:正确
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
char filename[50];
char buf[1000];
FILE* maps;
pid_t pid=getpid(); //进程号
unsigned long long s_addr,e_addr; //内存起始地址、终止地址
sprintf(filename,"/proc/%d/maps",pid); //文件地址
maps=fopen(filename,"r");
while(fgets(buf,1000,maps)!=NULL) //读一行
{
sscanf(buf,"%llx-%llx",&s_addr,&e_addr);
s_addr>>=12;
e_addr>>=12; //去掉VPO
for(;s_addr!=e_addr;s_addr++)
printf("%llu\n",s_addr);
}
return 0;
}
fd1=3.fd2=4,close之后新的fd2仍等于4
所以输出为:fd2=4
if(Fork()==0)
{
char* filename=argv[3];
int fd=open(filename,O_RDONLY,0);
dup2(fd,STDIN_FILENO);
close(fd);
Execve("fststcheck",argv,envp);
}
进程对 | 并发地? |
---|---|
AB | NO |
AC | YES |
AD | YES |
BC | YES |
BD | YES |
CD | YES |
父进程输出1,父进程的子进程输出0,子进程输出12,子进程的子进程输出02,
他们之间的相对顺序不固定,所以ACE都有可能
#include "csapp.h"
#define N 2
int main()
{
int status,i;
pid_t pid;
int sig;
char errinfo[100]={0};
/*parent creates N children*/
for(int 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))
{
sig=WTERMSIG(status);
sprintf(errinfo,"child %d terminated by signal %d",pid,sig);
psignal(sig,errinfo);
}
}
/*the only normal termination is if there are no more children*/
if(errno!=ECHILD)
unix_error("waitpid error");
exit(0);
}
第一题:正确
第二题:正确
第三题:正确
第四题:正确
第五题:错误
符号 | symtab条目? | 符号类型 | 定义符号的模块 | 节 |
---|---|---|---|---|
buf | Y | 外部 | m.o | .data |
bufp0 | Y | 全局 | swap.o | .data |
bufp1 | Y | 局部 | swap.o | .bss |
swap | Y | 全局 | swap.o | .text |
temp | N | —— | —— | —— |
incr | Y | 局部 | swap.o | .text |
count | Y | 局部 | swap.o | .data |
/*bar5.c*/
static double x;
void f()
{
x=-0.0;
}
(1)0x4004f8-0x4004ee=0xa
(2)0x400500-0x4004de=0x22
(1)libc.a包含1672个目标文件
libm.a包含481个目标文件
(2)相同
(3)linux-vdso.so.1 libc.so.6
第一题:有一处错误
第二题:正确
第三题:正确
第四题:正确
A.!(x^-1)
B.!(x^0)
C.!((x&0xff)^0xff)
D.!(x>>(sizeof(int)*8-8))
int int_shifts_are_arithmetic()
{
int x=-1>>(sizeof(int)*8-1);//log:x=1,ari:x=-1
if(!(x^1))return 0;
else return 1;
}
int odd_ones(unsigned x)
{
x^=x>>16;
x^=x>>8;
x^=x>>4;
x^=x>>2;
x^=x>>1;
return x%2;
}
第一题:A、B正确,C、D有误
第二题:有误
第三题:正确
208 011101010 208
-7/1024 100000111 -7/1024
5/(2^17) 000000000 1/1024
-2^12 111110000 负无穷
768 011110000 正无穷
float_bits float_negate(float_bits f)
{
unsigned sign=f>>31;
unsigned exp=f>>23&0xff;
unsigned frac=f&0x7fffff;
if(exp==0xff&&frac!=0)
return f;
else
return ((!sign)<<31)|(exp<<23)|frac;
}
int float_f2i(float_bits f)
{
const int bias=127;
int sign=f>>31;
int exp=((f>>23)&0xff)-bias;//2的指数位
int frac=f&0x7fffff+(1<<23);//加上前导1之后的完整的小数部分
int ans;
if(exp>30)//int最大是2^31-1,最多可以往左移30位,大于30就out of range
return 0x80000000;
else if(exp>23)//保证位运算的位数是正数
ans=frac<<(exp-23);//实质是先向右移23位再向左移exp,防止丢失数据
else
ans=frac>>(23-exp);
if(sign==1)
return -ans;
else return ans;
}
第一题:有1个错误
第二题:有误
第三题:正确
A. x in %rdi, n in %rsi, result in %rax, mask in %rdx
B. result=0;mask=1;
C. mask!=0
D. mask<<(n&0xff)
E. result|=(x&mask)
F.
long loop(long x,int n)
{
long result=0;
long mask;
for(mask=1;mask!=0;mask=mask<<(n&0xff)){
result|=x&mask;
}
return result;
}
typedef enum{MODE_A,MODE_B,MODE_C,MODE_D,MODE_E} mode_t;
long switch3(long *p1,long *p2,mode_t action)
{
long result=0;
switch(action)
{
case(MODE_A):
{
result=*p2;
action=(mode_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;
}
default:
{
result=12;
break;
}
}
return result;
}
A.
&A[i][j][k]=Xa+8*(S*T*i+T*j+k); //A的起始位置标为Xa
B. 根据原汇编代码可以得出
store_ele:
leaq (%rsi,%rsi,2),%rax //%rax=3*j;
leaq (%rsi,%rax,4),%rax //%rax=13*j;
movq %rdi,%rsi //%rsi=i;
salq $6,%rsi //%rsi=i<<6;
addq %rsi,%rdi //%rdi=65i;
addq %rax,%rdi //%rdx=65i+13j;
addq %rdi,%rdx //%rdx=65i+13j+k;
movq A(,%rdx,8),%rax //%rax=A[8*%rdx];
movq %rax,(%rcx) //*dest=%rax;
movl $3640,%eax
ret //return 3640;
所以A[R][S][T]的总字节数是3640,一个long长整型占据8个字节,所以总共存有455个long型变量
根据上一题中的公式以及%rdx=65i+13j+k,可以算出T=13,S=65/13=5,R=455/65=7
第一题:正确
第二题:正确
第三题:正确
由汇编代码可以得出:
q->t=*(q+8);
q->u=*(q+32);
p->y=*(p+184);
因为p->y必须要和8的整数倍地址对齐,所以x[A][B]的大小4 * A * B一定在176~184之间,即44<A * B<=46
同理,q->t必须和4的整数倍地址对齐,q->u必须要和8的整数倍地址对齐,所以4<B<=8,6<A<=10
所以整数A,B的唯一解是A=9,B=5
由汇编代码可以得出:
bp->last=(bp+288)
sizeof(a[i])=40;//由%rax=&(40*%rdi+%rsi)得出
CNT=7;//又因为%rdx=*(%rax+8),而%rdx最终存的是ap->idx的值,所以8就是bp->a的偏移量,所以a[]总共占据了280字节
sizeof(ap->x[ap->idx])=8;//由*(%rax+0x10+%rdx*8)得出
long x[4];//0x10=a的偏移量8+x的偏移量8,所以x中的元素个数是(40-8)/8=4;
sizeof(idx)=8;//first只有四个字节,a却偏移了8个字节,所以a_struct中的元素idx是long类型
答案:
CNT=7;
typedef struct
{
long idx;
long x[4];
}a_struct;
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->e1.y;
}
第一题:正确
第二题:正确
第三题:正确
void bubble_a(long *data,long count)
{
long i,last;
for(last=count-1;last>0;last--)
{
for(i=0;i<last;i++)
if(*(data+i)>*(data+i+1))
{
long t;
t=*(data+i+1);
*(data+i+1)=*(data+i);
*(data+i)=t;
}
}
}
bubble_a:
pushl %ebp
rrmovl %esp,%ebp
mrmovl 8(%ebp),%eax #count
mrmovl 12(%ebp),%esi #data
irmovl $1,%ebx
subl %ebx,%eax #last=count-1
Loop1:
andl %eax,%eax #last>0?
jle Done
xorl %ecx,%ecx #i=0
Loop2:
subl %eax,%ecx #i<last?
jge Loop3
addl %eax,%ecx #true i
addl %ecx,%esi #data+i
mrmovl (%esi),%edi #*(data+i)
mrmovl 4(%esi),%edx #*(data+i+1)
subl %edx,%edi #*(data+i)>*(data+i+1)?
jle Condition
addl %edx,%edi #true *(data+i)
rrmovl %edx,%ebx #t=*(data+i+1);
rrmovl %edi,%edx #*(data+i+1)=*(data+i);
rrmovl %ebx,%edi #*(data+i)=t;
rmmovl %edi,(%esi) #write *(data+i)
rmmovl %edx,4(%esi) #write *(data+i+1)
Condition:
subl %ecx,%esi #true data
irmovl $1,%ebx
addl %ebx,%ecx #i++
jmp Loop2
Loop3:
irmovl $1,%ebx
subl %ebx,%eax #last--
jmp Loop1
Done:
popl %ebp
ret
#Fetch stage#
word f_predPC = [
f_icode == IJXX && J_YES : f_valC;
f_code == ICALL : f_valC;
f_code == IJXX && f_valC < f_valP : f_valC;
1: valP;
]
word f_pc = [
M_icode == IJXX && !M_Cnd && M_valC < M_valP : M_valA;
M_icode == IJXX && M_Cnd && M_valC >= M_valP : M_valA;
W_icode == IRET : W_valM;
1 : F_predPC;
]
#Execute stage#
int E_valP = D_valP;
#Memory stage#
int M_valP = E_valP;
int M_valC = E_valC;
A.
循环寄存器%xmm0上的浮点加法形成关键路径
B.3.0
C.1.0
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;
for(i=0;i<length-5;i+=6)
{
sum=sum+udata[i]*vdata[i];
sum=sum+udata[i+1]*vdata[i+1];
sum=sum+udata[i+2]*vdata[i+2];
sum=sum+udata[i+3]*vdata[i+3];
sum=sum+udata[i+4]*vdata[i+4];
sum=sum+udata[i+5]*vdata[i+5];
}
for(;i<length;i++)
{
sum=sum+udata[i]*vdata[i];
}
*dest=sum;
}
A.无论展开多少次、如何改变结合顺序,循环展开时至少有一个sum的整数加法是需要顺序进行的,而整数加法的延迟界限是1.00
B.sum的浮点加法仍然是顺序操作,要受到延迟界限的限制
第一题:Y86有点小问题
第二题:有误
第三题:少画了个图
第四题:i<length处有问题