Showing preview only (1,108K chars total). Download the full file or copy to clipboard to get everything.
Repository: mofaph/csapp
Branch: master
Commit: 269dba3478ff
Files: 332
Total size: 941.5 KB
Directory structure:
gitextract_brtqdnlq/
├── .gitignore
├── README
├── bin/
│ ├── d2h
│ └── h2d
├── code/
│ ├── conc/
│ │ ├── badcnt.c
│ │ ├── ctime_ts.c
│ │ ├── echo_cnt.c
│ │ ├── echoserverp.c
│ │ ├── echoservers.c
│ │ ├── echoservert.c
│ │ ├── echoservert_pre.c
│ │ ├── hello.c
│ │ ├── hellobug.c
│ │ ├── norace.c
│ │ ├── psum.c
│ │ ├── race.c
│ │ ├── rand.c
│ │ ├── rand_r.c
│ │ ├── sbuf.c
│ │ ├── sbuf.h
│ │ ├── select.c
│ │ ├── sharing.c
│ │ └── tfgets-main.c
│ ├── data/
│ │ └── show-bytes.c
│ ├── ecf/
│ │ ├── alarm.c
│ │ ├── counterprob.c
│ │ ├── fork.c
│ │ ├── forkprob0.c
│ │ ├── forkprob1.c
│ │ ├── forkprob2.c
│ │ ├── forkprob3.c
│ │ ├── forkprob4.c
│ │ ├── forkprob5.c
│ │ ├── forkprob6.c
│ │ ├── forkprob7.c
│ │ ├── forkprob8.c
│ │ ├── hello-asm.sa
│ │ ├── kill.c
│ │ ├── procmask1.c
│ │ ├── procmask2.c
│ │ ├── restart.c
│ │ ├── rfork.c
│ │ ├── setjmp.c
│ │ ├── shellex.c
│ │ ├── sigint1.c
│ │ ├── signal1.c
│ │ ├── signal2.c
│ │ ├── signal3.c
│ │ ├── signal4.c
│ │ ├── signalprob0.c
│ │ ├── waitpid1.c
│ │ ├── waitpid2.c
│ │ ├── waitprob0.c
│ │ ├── waitprob1.c
│ │ └── waitprob3.c
│ ├── include/
│ │ └── csapp.h
│ ├── intro/
│ │ └── hello.c
│ ├── io/
│ │ ├── cpfile.c
│ │ ├── cpstdin.c
│ │ └── statcheck.c
│ ├── link/
│ │ ├── addvec.c
│ │ ├── dll.c
│ │ ├── elfstructs.c
│ │ ├── main.c
│ │ ├── main2.c
│ │ ├── multvec.c
│ │ ├── p-exe.d
│ │ ├── pdata-exe.d
│ │ └── swap.c
│ ├── mem/
│ │ ├── matmult/
│ │ │ └── mm.c
│ │ └── mountain/
│ │ └── mountain.c
│ ├── netp/
│ │ ├── echo.c
│ │ ├── echoclient.c
│ │ ├── echoserveri.c
│ │ ├── hostinfo.c
│ │ └── tiny/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ └── tiny.c
│ ├── src/
│ │ └── csapp.c
│ └── vm/
│ ├── malloc/
│ │ ├── memlib.c
│ │ └── mm.c
│ ├── memlib.h
│ └── mm.h
├── common/
│ ├── csapp.c
│ └── csapp.h
├── exercise/
│ ├── 00-topic.txt
│ ├── README
│ ├── ex10-10.c
│ ├── ex10-2.c
│ ├── ex10-3.c
│ ├── ex10-5.c
│ ├── ex10-6.c
│ ├── ex10-7.c
│ ├── ex10-8.c
│ ├── ex10-9.txt
│ ├── ex11-10/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-11/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-12/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-13/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-2.c
│ ├── ex11-3.c
│ ├── ex11-6/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-7/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-8/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-9/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex12-22.c
│ ├── ex2-36.c
│ ├── ex2-42.c
│ ├── ex2-58.c
│ ├── ex2-59.c
│ ├── ex2-60.c
│ ├── ex2-61.c
│ ├── ex2-62.c
│ ├── ex2-63.c
│ ├── ex2-64.c
│ ├── ex2-65.c
│ ├── ex2-66.c
│ ├── ex2-67.c
│ ├── ex2-68.c
│ ├── ex2-69.c
│ ├── ex2-7.c
│ ├── ex2-70.c
│ ├── ex2-71.c
│ ├── ex2-72.c
│ ├── ex2-73.c
│ ├── ex2-74.c
│ ├── ex2-75.c
│ ├── ex2-76.c
│ ├── ex2-77.c
│ ├── ex2-78.c
│ ├── ex2-79.c
│ ├── ex2-80.c
│ ├── ex2-81.c
│ ├── ex2-82.txt
│ ├── ex2-83.c
│ ├── ex2-84.txt
│ ├── ex2-85.txt
│ ├── ex2-86.txt
│ ├── ex2-87.txt
│ ├── ex2-88.txt
│ ├── ex2-89.c
│ ├── ex2-90.txt
│ ├── ex2-91.c
│ ├── ex2-92.c
│ ├── ex2-93.c
│ ├── ex2-94.c
│ ├── ex2-95.c
│ ├── ex2-96.c
│ ├── ex3-19.c
│ ├── ex3-34.c
│ ├── ex3-54.c
│ ├── ex3-55.asm
│ ├── ex3-56.txt
│ ├── ex3-57.c
│ ├── ex3-58.c
│ ├── ex3-59.c
│ ├── ex3-60.txt
│ ├── ex3-61.c
│ ├── ex3-62.c
│ ├── ex3-63.txt
│ ├── ex3-64.txt
│ ├── ex3-65.txt
│ ├── ex3-66.txt
│ ├── ex3-67.c
│ ├── ex3-68.c
│ ├── ex3-69.c
│ ├── ex3-70.c
│ ├── ex7-10.txt
│ ├── ex7-11.txt
│ ├── ex7-12.txt
│ ├── ex7-13.txt
│ ├── ex7-14.txt
│ ├── ex7-15.txt
│ ├── ex7-6.txt
│ ├── ex7-7.c
│ ├── ex7-8.txt
│ ├── ex7-9.txt
│ ├── ex8-10.txt
│ ├── ex8-11.c
│ ├── ex8-12.c
│ ├── ex8-13.c
│ ├── ex8-14.c
│ ├── ex8-15.c
│ ├── ex8-16.c
│ ├── ex8-17.txt
│ ├── ex8-18.c
│ ├── ex8-19.txt
│ ├── ex8-2.c
│ ├── ex8-20.c
│ ├── ex8-21.c
│ ├── ex8-22.c
│ ├── ex8-23.txt
│ ├── ex8-24.c
│ ├── ex8-25.c
│ ├── ex8-26/
│ │ ├── Makefile
│ │ ├── job.c
│ │ ├── job.h
│ │ ├── random_fork.c
│ │ ├── shellex.c
│ │ └── t-job.c
│ ├── ex8-3.c
│ ├── ex8-4.c
│ ├── ex8-5.c
│ ├── ex8-6.c
│ ├── ex8-7.c
│ ├── ex8-8.c
│ ├── ex8-9.txt
│ ├── ex9-14.c
│ ├── ex9-17.c
│ ├── ex9-18.c
│ ├── ex9-20/
│ │ ├── Makefile
│ │ ├── ex9-20.c
│ │ ├── t-block-operate.c
│ │ ├── t-block-quick-sort.c
│ │ ├── t-malloc.c
│ │ ├── t2.c
│ │ ├── t3.c
│ │ └── t9-20.c
│ ├── ex9-5.c
│ ├── ex9-8.c
│ ├── ex9-9.c
│ ├── t2-59.c
│ ├── t2-95.c
│ ├── t2-96.c
│ ├── t3-68.sh
│ ├── t8-22.c
│ ├── t8-25.c
│ ├── t9-14.c
│ ├── t9-14.sh
│ └── t9-17.c
├── hard-task.txt
├── missing.c
├── notes/
│ ├── .gitignore
│ ├── api.txt
│ ├── ch03.txt
│ ├── ch07.txt
│ ├── ch08.txt
│ ├── ch09.txt
│ └── ch11.txt
└── sample/
├── .gitignore
├── ch02/
│ ├── .gitignore
│ └── show-bytes.c
├── ch03/
│ ├── buf-overflow.c
│ ├── code.c
│ ├── main.c
│ ├── simple.c
│ └── simple_1.c
├── ch07/
│ ├── .gitignore
│ ├── addvec.c
│ ├── bar1.c
│ ├── bar2.c
│ ├── bar3.c
│ ├── bar4.c
│ ├── bar5.c
│ ├── dll.c
│ ├── foo1.c
│ ├── foo2.c
│ ├── foo3.c
│ ├── foo4.c
│ ├── foo5.c
│ ├── linkerror.c
│ ├── main.c
│ ├── main2.c
│ ├── multvec.c
│ ├── swap.c
│ └── vector.h
├── ch08/
│ ├── .gitignore
│ ├── alarm.c
│ ├── fork.c
│ ├── hello-asm.sa
│ ├── kill.c
│ ├── procmask1.c
│ ├── procmask2.c
│ ├── restart.c
│ ├── rfork.c
│ ├── setjmp.c
│ ├── shellex.c
│ ├── sigint1.c
│ ├── signal1.c
│ ├── signal2.c
│ ├── signal3.c
│ ├── signal4.c
│ ├── waitpid1.c
│ └── waitpid2.c
├── ch09/
│ ├── .gitignore
│ ├── memlib.c
│ ├── mm-test.c
│ └── mm.c
├── ch10/
│ ├── .gitignore
│ ├── cpfile.c
│ ├── cpstdin.c
│ └── statcheck.c
├── ch11/
│ ├── echo.c
│ ├── echoclient.c
│ ├── echoserveri.c
│ ├── hostinfo.c
│ └── tiny/
│ ├── cgi-bin/
│ │ └── adder.c
│ ├── home.html
│ ├── rfc2616.txt
│ └── tiny.c
└── ch12/
├── Makefile
├── badcnt.c
├── echo_cnt.c
├── echoserverp.c
├── echoservers.c
├── echoservert.c
├── echoservert_pre.c
├── goodcnt.c
├── hello.c
├── sbuf.c
├── sbuf.h
├── select.c
└── sharing.c
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
test.c
t.c
a.out
missing
TAGS
tags
# Object files
*.o
*.s
# Libraries
*.lib
*.a
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
================================================
FILE: README
================================================
================================================================================
深入理解计算机系统·第二版
Randal E. Bryant David R. O'Hallaron 著
龚奕利 雷迎春 译
机械工业出版社
2012 年 7 月第 1 版第 8 次印刷
ISBN: 978-7-111-32133-0
================================================================================
注意:
这个仓库是本人自己学习的过程中,记录下来的一些读书笔记和个人的习题解答。
这里面的习题解答将会有许多的错误,请你不要依赖它们的正确性。在这里,欢迎
指出任何错误。
在这个仓库中,除了主分支之外,其他的分支将会消失。所以,请你不要在非主分
支的基础上做任何的修改。如果你做出了修改,希望这些更新合并到这个仓库的主
分支中,那么请你新建一个分支,然后再修改。
顶层各个目录的说明:
bin/ 可执行文件
code/ 书本中的示例代码
common/ 共享代码
exercise/ 家庭作业的题目和个人的解答
notes/ 读书笔记
sample/ 手动录入的示例代码
missing.c 这个程序输出还没有完成的家庭作业的题号
官方网站:http://csapp.cs.cmu.edu/
官方学生资源:http://csapp.cs.cmu.edu/public/students.html
中文版勘误:http://www.yiligong.org/csapp2e/
豆瓣书评:http://book.douban.com/subject/5333562/
卓越书评:http://goo.gl/rhpVY
mofaph
2012/11/24
================================================
FILE: bin/d2h
================================================
#!/usr/bin/perl
# Convert list of decimal numbers into hex
# 将十进制数字转化为十六进制数字
# 用法:
# $ ./d2h 100 500 751
# 100=0x64
# 500=0x1f4
# 751=0x2ef
for ($i = 0; $i < @ARGV; $i++) {
printf("%d=0x%x\n", $ARGV[$i], $ARGV[$i]);
}
================================================
FILE: bin/h2d
================================================
#!/usr/bin/perl
# Convert list of hex numbers into decimal
# 将十六进制数字转化为十进制数字
# 用法:
# $ ./h2d 100 0x500 0x751
# 0x100=256
# 0x500=1280
# 0x751=1873
for ($i = 0; $i < @ARGV; $i++) {
$val = hex($ARGV[$i]);
printf("0x%x=%d\n", $val, $val);
}
================================================
FILE: code/conc/badcnt.c
================================================
/*
* badcnt.c - An improperly synchronized counter program
*/
/* $begin badcnt */
#include "csapp.h"
void *thread(void *vargp); /* Thread routine prototype */
/* Global shared variable */
volatile int cnt = 0; /* Counter */
int main(int argc, char **argv)
{
int niters;
pthread_t tid1, tid2;
/* Check input argument */
if (argc != 2) {
printf("usage: %s <niters>\n", argv[0]);
exit(0);
}
niters = atoi(argv[1]);
/* Create threads and wait for them to finish */
Pthread_create(&tid1, NULL, thread, &niters);
Pthread_create(&tid2, NULL, thread, &niters);
Pthread_join(tid1, NULL);
Pthread_join(tid2, NULL);
/* Check result */
if (cnt != (2 * niters))
printf("BOOM! cnt=%d\n", cnt);
else
printf("OK cnt=%d\n", cnt);
exit(0);
}
/* Thread routine */
void *thread(void *vargp)
{
int i, niters = *((int *)vargp);
for (i = 0; i < niters; i++) //line:conc:badcnt:beginloop
cnt++; //line:conc:badcnt:endloop
return NULL;
}
/* $end badcnt */
================================================
FILE: code/conc/ctime_ts.c
================================================
/*
* ctime_ts - A thread-safe wrapper for ctime
*/
#include "csapp.h"
#define MAXSTR 128
static sem_t mutex; /* protects calls to ctime */
static void init_ctime_ts(void)
{
Sem_init(&mutex, 0, 1);
}
/* $begin ctime_ts */
char *ctime_ts(const time_t *timep, char *privatep)
{
char *sharedp;
P(&mutex);
sharedp = ctime(timep);
strcpy(privatep, sharedp); /* Copy string from shared to private */
V(&mutex);
return privatep;
}
/* $end ctime_ts */
int main()
{
char timestr[MAXSTR];
time_t timeval;
/* Thread-safe code to print the current time string */
init_ctime_ts();
timeval = time(NULL);
ctime_ts(&timeval, timestr);
printf("%s", timestr);
exit(0);
}
================================================
FILE: code/conc/echo_cnt.c
================================================
/*
* A thread-safe version of echo that counts the total number
* of bytes received from clients.
*/
/* $begin echo_cnt */
#include "csapp.h"
static int byte_cnt; /* byte counter */
static sem_t mutex; /* and the mutex that protects it */
static void init_echo_cnt(void)
{
Sem_init(&mutex, 0, 1);
byte_cnt = 0;
}
void echo_cnt(int connfd)
{
int n;
char buf[MAXLINE];
rio_t rio;
static pthread_once_t once = PTHREAD_ONCE_INIT;
Pthread_once(&once, init_echo_cnt); //line:conc:pre:pthreadonce
Rio_readinitb(&rio, connfd); //line:conc:pre:rioinitb
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
P(&mutex);
byte_cnt += n; //line:conc:pre:cntaccess1
printf("thread %d received %d (%d total) bytes on fd %d\n",
(int) pthread_self(), n, byte_cnt, connfd); //line:conc:pre:cntaccess2
V(&mutex);
Rio_writen(connfd, buf, n);
}
}
/* $end echo_cnt */
================================================
FILE: code/conc/echoserverp.c
================================================
/*
* echoserverp.c - A concurrent echo server based on processes
*/
/* $begin echoserverpmain */
#include "csapp.h"
void echo(int connfd);
void sigchld_handler(int sig) //line:conc:echoserverp:handlerstart
{
while (waitpid(-1, 0, WNOHANG) > 0)
;
return;
} //line:conc:echoserverp:handlerend
int main(int argc, char **argv)
{
int listenfd, connfd, port;
socklen_t clientlen=sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
Signal(SIGCHLD, sigchld_handler);
listenfd = Open_listenfd(port);
while (1) {
connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen);
if (Fork() == 0) {
Close(listenfd); /* Child closes its listening socket */
echo(connfd); /* Child services client */ //line:conc:echoserverp:echofun
Close(connfd); /* Child closes connection with client */ //line:conc:echoserverp:childclose
exit(0); /* Child exits */
}
Close(connfd); /* Parent closes connected socket (important!) */ //line:conc:echoserverp:parentclose
}
}
/* $end echoserverpmain */
================================================
FILE: code/conc/echoservers.c
================================================
/*
* echoservers.c - A concurrent echo server based on select
*/
/* $begin echoserversmain */
#include "csapp.h"
typedef struct { /* represents a pool of connected descriptors */ //line:conc:echoservers:beginpool
int maxfd; /* largest descriptor in read_set */
fd_set read_set; /* set of all active descriptors */
fd_set ready_set; /* subset of descriptors ready for reading */
int nready; /* number of ready descriptors from select */
int maxi; /* highwater index into client array */
int clientfd[FD_SETSIZE]; /* set of active descriptors */
rio_t clientrio[FD_SETSIZE]; /* set of active read buffers */
} pool; //line:conc:echoservers:endpool
/* $end echoserversmain */
void init_pool(int listenfd, pool *p);
void add_client(int connfd, pool *p);
void check_clients(pool *p);
/* $begin echoserversmain */
int byte_cnt = 0; /* counts total bytes received by server */
int main(int argc, char **argv)
{
int listenfd, connfd, port;
socklen_t clientlen = sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
static pool pool;
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
listenfd = Open_listenfd(port);
init_pool(listenfd, &pool); //line:conc:echoservers:initpool
while (1) {
/* Wait for listening/connected descriptor(s) to become ready */
pool.ready_set = pool.read_set;
pool.nready = Select(pool.maxfd+1, &pool.ready_set, NULL, NULL, NULL);
/* If listening descriptor ready, add new client to pool */
if (FD_ISSET(listenfd, &pool.ready_set)) { //line:conc:echoservers:listenfdready
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); //line:conc:echoservers:accept
add_client(connfd, &pool); //line:conc:echoservers:addclient
}
/* Echo a text line from each ready connected descriptor */
check_clients(&pool); //line:conc:echoservers:checkclients
}
}
/* $end echoserversmain */
/* $begin init_pool */
void init_pool(int listenfd, pool *p)
{
/* Initially, there are no connected descriptors */
int i;
p->maxi = -1; //line:conc:echoservers:beginempty
for (i=0; i< FD_SETSIZE; i++)
p->clientfd[i] = -1; //line:conc:echoservers:endempty
/* Initially, listenfd is only member of select read set */
p->maxfd = listenfd; //line:conc:echoservers:begininit
FD_ZERO(&p->read_set);
FD_SET(listenfd, &p->read_set); //line:conc:echoservers:endinit
}
/* $end init_pool */
/* $begin add_client */
void add_client(int connfd, pool *p)
{
int i;
p->nready--;
for (i = 0; i < FD_SETSIZE; i++) /* Find an available slot */
if (p->clientfd[i] < 0) {
/* Add connected descriptor to the pool */
p->clientfd[i] = connfd; //line:conc:echoservers:beginaddclient
Rio_readinitb(&p->clientrio[i], connfd); //line:conc:echoservers:endaddclient
/* Add the descriptor to descriptor set */
FD_SET(connfd, &p->read_set); //line:conc:echoservers:addconnfd
/* Update max descriptor and pool highwater mark */
if (connfd > p->maxfd) //line:conc:echoservers:beginmaxfd
p->maxfd = connfd; //line:conc:echoservers:endmaxfd
if (i > p->maxi) //line:conc:echoservers:beginmaxi
p->maxi = i; //line:conc:echoservers:endmaxi
break;
}
if (i == FD_SETSIZE) /* Couldn't find an empty slot */
app_error("add_client error: Too many clients");
}
/* $end add_client */
/* $begin check_clients */
void check_clients(pool *p)
{
int i, connfd, n;
char buf[MAXLINE];
rio_t rio;
for (i = 0; (i <= p->maxi) && (p->nready > 0); i++) {
connfd = p->clientfd[i];
rio = p->clientrio[i];
/* If the descriptor is ready, echo a text line from it */
if ((connfd > 0) && (FD_ISSET(connfd, &p->ready_set))) {
p->nready--;
if ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
byte_cnt += n; //line:conc:echoservers:beginecho
printf("Server received %d (%d total) bytes on fd %d\n",
n, byte_cnt, connfd);
Rio_writen(connfd, buf, n); //line:conc:echoservers:endecho
}
/* EOF detected, remove descriptor from pool */
else {
Close(connfd); //line:conc:echoservers:closeconnfd
FD_CLR(connfd, &p->read_set); //line:conc:echoservers:beginremove
p->clientfd[i] = -1; //line:conc:echoservers:endremove
}
}
}
}
/* $end check_clients */
================================================
FILE: code/conc/echoservert.c
================================================
/*
* echoservert.c - A concurrent echo server using threads
*/
/* $begin echoservertmain */
#include "csapp.h"
void echo(int connfd);
void *thread(void *vargp);
int main(int argc, char **argv)
{
int listenfd, *connfdp, port;
socklen_t clientlen=sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
pthread_t tid;
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
listenfd = Open_listenfd(port);
while (1) {
connfdp = Malloc(sizeof(int)); //line:conc:echoservert:beginmalloc
*connfdp = Accept(listenfd, (SA *) &clientaddr, &clientlen); //line:conc:echoservert:endmalloc
Pthread_create(&tid, NULL, thread, connfdp);
}
}
/* thread routine */
void *thread(void *vargp)
{
int connfd = *((int *)vargp);
Pthread_detach(pthread_self()); //line:conc:echoservert:detach
Free(vargp); //line:conc:echoservert:free
echo(connfd);
Close(connfd);
return NULL;
}
/* $end echoservertmain */
================================================
FILE: code/conc/echoservert_pre.c
================================================
/*
* echoservert_pre.c - A prethreaded concurrent echo server
*/
/* $begin echoservertpremain */
#include "csapp.h"
#include "sbuf.h"
#define NTHREADS 4
#define SBUFSIZE 16
void echo_cnt(int connfd);
void *thread(void *vargp);
sbuf_t sbuf; /* shared buffer of connected descriptors */
int main(int argc, char **argv)
{
int i, listenfd, connfd, port;
socklen_t clientlen=sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
pthread_t tid;
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
sbuf_init(&sbuf, SBUFSIZE); //line:conc:pre:initsbuf
listenfd = Open_listenfd(port);
for (i = 0; i < NTHREADS; i++) /* Create worker threads */ //line:conc:pre:begincreate
Pthread_create(&tid, NULL, thread, NULL); //line:conc:pre:endcreate
while (1) {
connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen);
sbuf_insert(&sbuf, connfd); /* Insert connfd in buffer */
}
}
void *thread(void *vargp)
{
Pthread_detach(pthread_self());
while (1) {
int connfd = sbuf_remove(&sbuf); /* Remove connfd from buffer */ //line:conc:pre:removeconnfd
echo_cnt(connfd); /* Service client */
Close(connfd);
}
}
/* $end echoservertpremain */
================================================
FILE: code/conc/hello.c
================================================
/*
* hello.c - Pthreads "hello, world" program
*/
/* $begin hello */
#include "csapp.h"
void *thread(void *vargp); //line:conc:hello:prototype
int main() //line:conc:hello:main
{
pthread_t tid; //line:conc:hello:tid
Pthread_create(&tid, NULL, thread, NULL); //line:conc:hello:create
Pthread_join(tid, NULL); //line:conc:hello:join
exit(0); //line:conc:hello:exit
}
void *thread(void *vargp) /* thread routine */ //line:conc:hello:beginthread
{
printf("Hello, world!\n");
return NULL; //line:conc:hello:return
} //line:conc:hello:endthread
/* $end hello */
================================================
FILE: code/conc/hellobug.c
================================================
/*
* hellobug.c - "hello, world" program with a bug
*/
/* $begin hellobug */
#include "csapp.h"
void *thread(void *vargp);
int main()
{
pthread_t tid;
Pthread_create(&tid, NULL, thread, NULL);
exit(0);
}
/* thread routine */
void *thread(void *vargp)
{
Sleep(1);
printf("Hello, world!\n");
return NULL;
}
/* $end hellobug */
================================================
FILE: code/conc/norace.c
================================================
/*
* norace.c - fixes the race in race.c
*/
/* $begin norace */
#include "csapp.h"
#define N 4
void *thread(void *vargp);
int main()
{
pthread_t tid[N];
int i, *ptr;
for (i = 0; i < N; i++) {
ptr = Malloc(sizeof(int)); //line:conc:norace:createthread1
*ptr = i; //line:conc:norace:createthread2
Pthread_create(&tid[i], NULL, thread, ptr); //line:conc:norace:createthread3
} //line:conc:norace:endloop
for (i = 0; i < N; i++)
Pthread_join(tid[i], NULL);
exit(0);
}
/* thread routine */
void *thread(void *vargp)
{
int myid = *((int *)vargp);
Free(vargp);
printf("Hello from thread %d\n", myid);
return NULL;
}
/* $end norace */
================================================
FILE: code/conc/psum.c
================================================
/*
* psum.c - A simple parallel sum program
*/
/* $begin psum */
#include "csapp.h"
#define MAXTHREADS 32
void *sum(void *vargp);
/* Global shared variables */
long psum[MAXTHREADS]; /* Partial sum computed by each thread */
long nelems_per_thread; /* Number of elements summed by each thread */
int main(int argc, char **argv)
{
long i, nelems, log_nelems, nthreads, result = 0;
pthread_t tid[MAXTHREADS];
int myid[MAXTHREADS];
/* Get input arguments */
if (argc != 3) {
printf("Usage: %s <nthreads> <log_nelems>\n", argv[0]);
exit(0);
}
nthreads = atoi(argv[1]);
log_nelems = atoi(argv[2]);
nelems = (1L << log_nelems);
/* $end psum */
/* Check input arguments */
if ((nelems % nthreads) != 0 || (log_nelems > 31)) {
printf("Error: invalid nelems\n");
exit(0);
}
/* $begin psum */
nelems_per_thread = nelems / nthreads;
/* Create peer threads and wait for them to finish */
for (i = 0; i < nthreads; i++) { //line:conc:psum:createloop1
myid[i] = i; //line:conc:psum:createloop2
Pthread_create(&tid[i], NULL, sum, &myid[i]); //line:conc:psum:createloop3
} //line:conc:psum:createloop4
for (i = 0; i < nthreads; i++) //line:conc:psum:waitloop1
Pthread_join(tid[i], NULL); //line:conc:psum:waitloop2
/* Add up the partial sums computed by each thread */
for (i = 0; i < nthreads; i++) //line:conc:psum:sumloop1
result += psum[i]; //line:conc:psum:sumloop2
/* Check final answer */
if (result != (nelems * (nelems-1))/2) //line:conc:psum:check1
printf("Error: result=%ld\n", result); //line:conc:psum:check2
exit(0);
}
/* $end psum */
/* Thread routine */
/* $begin psum-thread */
void *sum(void *vargp)
{
int myid = *((int *)vargp); /* Extract the thread ID */ //line:conc:psum:extractid
long start = myid * nelems_per_thread; /* Start element index */ //line:conc:psum:getstart
long end = start + nelems_per_thread; /* End element index */ //line:conc:psum:getend
long i, sum = 0;
for (i = start; i < end; i++) { //line:conc:psum:threadsumloop1
sum += i; //line:conc:psum:threadsumloop2
} //line:conc:psum:threadsumloop3
psum[myid] = sum; //line:conc:psum:threadsum
return NULL;
}
/* $end psum-thread */
================================================
FILE: code/conc/race.c
================================================
/*
* race.c - demonstrates a race condition
*/
/* $begin race */
#include "csapp.h"
#define N 4
void *thread(void *vargp);
int main()
{
pthread_t tid[N];
int i;
for (i = 0; i < N; i++)
Pthread_create(&tid[i], NULL, thread, &i); //line:conc:race:createthread
for (i = 0; i < N; i++)
Pthread_join(tid[i], NULL);
exit(0);
}
/* thread routine */
void *thread(void *vargp)
{
int myid = *((int *)vargp); //line:conc:race:derefarg
printf("Hello from thread %d\n", myid);
return NULL;
}
/* $end race */
================================================
FILE: code/conc/rand.c
================================================
#include <stdio.h>
#include <stdlib.h>
/* $begin rand */
unsigned int next = 1;
/* rand - return pseudo-random integer on 0..32767 */
int rand(void)
{
next = next*1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
/* srand - set seed for rand() */
void srand(unsigned int seed)
{
next = seed;
}
/* $end rand */
int main()
{
srand(100);
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
exit(0);
}
================================================
FILE: code/conc/rand_r.c
================================================
#include <stdio.h>
#include <stdlib.h>
/* $begin rand_r */
/* rand_r - a reentrant pseudo-random integer on 0..32767 */
int rand_r(unsigned int *nextp)
{
*nextp = *nextp * 1103515245 + 12345;
return (unsigned int)(*nextp / 65536) % 32768;
}
/* $end rand_r */
int main()
{
unsigned int next = 1;
printf("%d\n", rand_r(&next));
printf("%d\n", rand_r(&next));
printf("%d\n", rand_r(&next));
exit(0);
}
================================================
FILE: code/conc/sbuf.c
================================================
/* $begin sbufc */
#include "csapp.h"
#include "sbuf.h"
/* Create an empty, bounded, shared FIFO buffer with n slots */
/* $begin sbuf_init */
void sbuf_init(sbuf_t *sp, int n)
{
sp->buf = Calloc(n, sizeof(int));
sp->n = n; /* Buffer holds max of n items */
sp->front = sp->rear = 0; /* Empty buffer iff front == rear */
Sem_init(&sp->mutex, 0, 1); /* Binary semaphore for locking */
Sem_init(&sp->slots, 0, n); /* Initially, buf has n empty slots */
Sem_init(&sp->items, 0, 0); /* Initially, buf has zero data items */
}
/* $end sbuf_init */
/* Clean up buffer sp */
/* $begin sbuf_deinit */
void sbuf_deinit(sbuf_t *sp)
{
Free(sp->buf);
}
/* $end sbuf_deinit */
/* Insert item onto the rear of shared buffer sp */
/* $begin sbuf_insert */
void sbuf_insert(sbuf_t *sp, int item)
{
P(&sp->slots); /* Wait for available slot */
P(&sp->mutex); /* Lock the buffer */
sp->buf[(++sp->rear)%(sp->n)] = item; /* Insert the item */
V(&sp->mutex); /* Unlock the buffer */
V(&sp->items); /* Announce available item */
}
/* $end sbuf_insert */
/* Remove and return the first item from buffer sp */
/* $begin sbuf_remove */
int sbuf_remove(sbuf_t *sp)
{
int item;
P(&sp->items); /* Wait for available item */
P(&sp->mutex); /* Lock the buffer */
item = sp->buf[(++sp->front)%(sp->n)]; /* Remove the item */
V(&sp->mutex); /* Unlock the buffer */
V(&sp->slots); /* Announce available slot */
return item;
}
/* $end sbuf_remove */
/* $end sbufc */
================================================
FILE: code/conc/sbuf.h
================================================
#ifndef __SBUF_H__
#define __SBUF_H__
#include "csapp.h"
/* $begin sbuft */
typedef struct {
int *buf; /* Buffer array */
int n; /* Maximum number of slots */
int front; /* buf[(front+1)%n] is first item */
int rear; /* buf[rear%n] is last item */
sem_t mutex; /* Protects accesses to buf */
sem_t slots; /* Counts available slots */
sem_t items; /* Counts available items */
} sbuf_t;
/* $end sbuft */
void sbuf_init(sbuf_t *sp, int n);
void sbuf_deinit(sbuf_t *sp);
void sbuf_insert(sbuf_t *sp, int item);
int sbuf_remove(sbuf_t *sp);
#endif /* __SBUF_H__ */
================================================
FILE: code/conc/select.c
================================================
/* $begin select */
#include "csapp.h"
void echo(int connfd);
void command(void);
int main(int argc, char **argv)
{
int listenfd, connfd, port;
socklen_t clientlen = sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
fd_set read_set, ready_set;
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
listenfd = Open_listenfd(port); //line:conc:select:openlistenfd
FD_ZERO(&read_set); /* Clear read set */ //line:conc:select:clearreadset
FD_SET(STDIN_FILENO, &read_set); /* Add stdin to read set */ //line:conc:select:addstdin
FD_SET(listenfd, &read_set); /* Add listenfd to read set */ //line:conc:select:addlistenfd
while (1) {
ready_set = read_set;
Select(listenfd+1, &ready_set, NULL, NULL, NULL); //line:conc:select:select
if (FD_ISSET(STDIN_FILENO, &ready_set)) //line:conc:select:stdinready
command(); /* Read command line from stdin */
if (FD_ISSET(listenfd, &ready_set)) { //line:conc:select:listenfdready
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
echo(connfd); /* Echo client input until EOF */
Close(connfd);
}
}
}
void command(void) {
char buf[MAXLINE];
if (!Fgets(buf, MAXLINE, stdin))
exit(0); /* EOF */
printf("%s", buf); /* Process the input command */
}
/* $end select */
================================================
FILE: code/conc/sharing.c
================================================
/* $begin sharing */
#include "csapp.h"
#define N 2
void *thread(void *vargp);
char **ptr; /* global variable */ //line:conc:sharing:ptrdec
int main()
{
int i;
pthread_t tid;
char *msgs[N] = {
"Hello from foo",
"Hello from bar"
};
ptr = msgs;
for (i = 0; i < N; i++)
Pthread_create(&tid, NULL, thread, (void *)i);
Pthread_exit(NULL);
}
void *thread(void *vargp)
{
int myid = (int)vargp;
static int cnt = 0; //line:conc:sharing:cntdec
printf("[%d]: %s (cnt=%d)\n", myid, ptr[myid], ++cnt); //line:conc:sharing:stack
return NULL;
}
/* $end sharing */
================================================
FILE: code/conc/tfgets-main.c
================================================
/* $begin tfgetsmain */
#include "csapp.h"
char *tfgets(char *s, int size, FILE *stream);
int main()
{
char buf[MAXLINE];
if (tfgets(buf, MAXLINE, stdin) == NULL)
printf("BOOM!\n");
else
printf("%s", buf);
exit(0);
}
/* $end tfgetsmain */
================================================
FILE: code/data/show-bytes.c
================================================
/* $begin show-bytes */
#include <stdio.h>
/* $end show-bytes */
#include <stdlib.h>
#include <string.h>
/* $begin show-bytes */
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len) {
int i;
for (i = 0; i < len; i++)
printf(" %.2x", start[i]); //line:data:show_bytes_printf
printf("\n");
}
void show_int(int x) {
show_bytes((byte_pointer) &x, sizeof(int)); //line:data:show_bytes_amp1
}
void show_float(float x) {
show_bytes((byte_pointer) &x, sizeof(float)); //line:data:show_bytes_amp2
}
void show_pointer(void *x) {
show_bytes((byte_pointer) &x, sizeof(void *)); //line:data:show_bytes_amp3
}
/* $end show-bytes */
/* $begin test-show-bytes */
void test_show_bytes(int val) {
int ival = val;
float fval = (float) ival;
int *pval = &ival;
show_int(ival);
show_float(fval);
show_pointer(pval);
}
/* $end test-show-bytes */
void simple_show_a() {
/* $begin simple-show-a */
int val = 0x87654321;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-a */
}
void simple_show_b() {
/* $begin simple-show-b */
int val = 0x12345678;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-b */
}
void float_eg() {
int x = 3490593;
float f = (float) x;
printf("For x = %d\n", x);
show_int(x);
show_float(f);
x = 3510593;
f = (float) x;
printf("For x = %d\n", x);
show_int(x);
show_float(f);
}
void string_ueg() {
/* $begin show-ustring */
const char *s = "ABCDEF";
show_bytes((byte_pointer) s, strlen(s));
/* $end show-ustring */
}
void string_leg() {
/* $begin show-lstring */
const char *s = "abcdef";
show_bytes((byte_pointer) s, strlen(s));
/* $end show-lstring */
}
void show_twocomp()
{
/* $begin show-twocomp */
short x = 12345;
short mx = -x;
show_bytes((byte_pointer) &x, sizeof(short));
show_bytes((byte_pointer) &mx, sizeof(short));
/* $end show-twocomp */
}
int main(int argc, char *argv[])
{
int val = 12345;
if (argc > 1) {
if (argc > 1) {
val = strtol(argv[1], NULL, 0);
}
printf("calling test_show_bytes\n");
test_show_bytes(val);
} else {
printf("calling show_twocomp\n");
show_twocomp();
printf("Calling simple_show_a\n");
simple_show_a();
printf("Calling simple_show_b\n");
simple_show_b();
printf("Calling float_eg\n");
float_eg();
printf("Calling string_ueg\n");
string_ueg();
printf("Calling string_leg\n");
string_leg();
}
return 0;
}
================================================
FILE: code/ecf/alarm.c
================================================
/* $begin alarm */
#include "csapp.h"
void handler(int sig)
{
static int beeps = 0;
printf("BEEP\n");
if (++beeps < 5)
Alarm(1); /* Next SIGALRM will be delivered in 1 second */
else {
printf("BOOM!\n");
exit(0);
}
}
int main()
{
Signal(SIGALRM, handler); /* install SIGALRM handler */
Alarm(1); /* Next SIGALRM will be delivered in 1s */
while (1) {
; /* Signal handler returns control here each time */
}
exit(0);
}
/* $end alarm */
================================================
FILE: code/ecf/counterprob.c
================================================
/* $begin counterprob */
#include "csapp.h"
int counter = 0;
void handler(int sig)
{
counter++;
sleep(1); /* Do some work in the handler */
return;
}
int main()
{
int i;
Signal(SIGUSR2, handler);
if (Fork() == 0) { /* Child */
for (i = 0; i < 5; i++) {
Kill(getppid(), SIGUSR2);
printf("sent SIGUSR2 to parent\n");
}
exit(0);
}
Wait(NULL);
printf("counter=%d\n", counter);
exit(0);
}
/* $end counterprob */
================================================
FILE: code/ecf/fork.c
================================================
/* $begin fork */
#include "csapp.h"
int main()
{
pid_t pid;
int x = 1;
pid = Fork(); //line:ecf:forkreturn
if (pid == 0) { /* Child */
printf("child : x=%d\n", ++x); //line:ecf:childprint
exit(0);
}
/* Parent */
printf("parent: x=%d\n", --x); //line:ecf:parentprint
exit(0);
}
/* $end fork */
================================================
FILE: code/ecf/forkprob0.c
================================================
/* $begin forkprob0 */
#include "csapp.h"
int main()
{
int x = 1;
if (Fork() == 0)
printf("printf1: x=%d\n", ++x);
printf("printf2: x=%d\n", --x);
exit(0);
}
/* $end forkprob0 */
================================================
FILE: code/ecf/forkprob1.c
================================================
/* $begin forkprob1 */
#include "csapp.h"
int main()
{
int i;
for (i = 0; i < 2; i++)
Fork();
printf("hello\n");
exit(0);
}
/* $end forkprob1 */
================================================
FILE: code/ecf/forkprob2.c
================================================
/* $begin forkprob2 */
#include "csapp.h"
void end(void)
{
printf("2");
}
int main()
{
if (Fork() == 0)
atexit(end);
if (Fork() == 0)
printf("0");
else
printf("1");
exit(0);
}
/* $end forkprob2 */
================================================
FILE: code/ecf/forkprob3.c
================================================
/* $begin forkprob3 */
#include "csapp.h"
int main()
{
int x = 3;
if (Fork() != 0)
printf("x=%d\n", ++x);
printf("x=%d\n", --x);
exit(0);
}
/* $end forkprob3 */
================================================
FILE: code/ecf/forkprob4.c
================================================
/* $begin forkprob4 */
#include "csapp.h"
void doit()
{
Fork();
Fork();
printf("hello\n");
return;
}
int main()
{
doit();
printf("hello\n");
exit(0);
}
/* $end forkprob4 */
================================================
FILE: code/ecf/forkprob5.c
================================================
/* $begin forkprob5 */
#include "csapp.h"
void doit()
{
if (Fork() == 0) {
Fork();
printf("hello\n");
exit(0);
}
return;
}
int main()
{
doit();
printf("hello\n");
exit(0);
}
/* $end forkprob5 */
================================================
FILE: code/ecf/forkprob6.c
================================================
/* $begin forkprob6 */
#include "csapp.h"
void doit()
{
if (Fork() == 0) {
Fork();
printf("hello\n");
return;
}
return;
}
int main()
{
doit();
printf("hello\n");
exit(0);
}
/* $end forkprob6 */
================================================
FILE: code/ecf/forkprob7.c
================================================
/* $begin forkprob7 */
#include "csapp.h"
int counter = 1;
int main()
{
if (fork() == 0) {
counter--;
exit(0);
}
else {
Wait(NULL);
printf("counter = %d\n", ++counter);
}
exit(0);
}
/* $end forkprob7 */
================================================
FILE: code/ecf/forkprob8.c
================================================
#include "csapp.h"
/* $begin forkprob8 */
void foo(int n)
{
int i;
for (i = 0; i < n; i++)
Fork();
printf("hello\n");
exit(0);
}
/* $end forkprob8 */
int main(int argc, char **argv)
{
if (argc < 2) {
printf("usage: %s <n>\n", argv[0]);
exit(0);
}
foo(atoi(argv[1]));
exit(0);
}
================================================
FILE: code/ecf/hello-asm.sa
================================================
/* $begin hello-s 1 */
.section .data
string:
.ascii "hello, world\n"
string_end:
.equ len, string_end - string
.section .text
.globl main
main:
# First, call write(1, "hello, world\n", 13)
movl $4, %eax # System call number 4
movl $1, %ebx # stdout has descriptor 1
movl $string, %ecx # Hello world string
movl $len, %edx # String length
int $0x80 # System call code
# Next, call exit(0)
movl $1, %eax # System call number 0
movl $0, %ebx # Argument is 0
int $0x80 # System call code
/* $end hello-s 1 */
================================================
FILE: code/ecf/kill.c
================================================
/* $begin kill */
#include "csapp.h"
int main()
{
pid_t pid;
/* Child sleeps until SIGKILL signal received, then dies */
if ((pid = Fork()) == 0) {
Pause(); /* Wait for a signal to arrive */
printf("control should never reach here!\n");
exit(0);
}
/* Parent sends a SIGKILL signal to a child */
Kill(pid, SIGKILL);
exit(0);
}
/* $end kill */
================================================
FILE: code/ecf/procmask1.c
================================================
#include "csapp.h"
void initjobs()
{
}
void addjob(int pid)
{
}
void deletejob(int pid)
{
}
/* $begin procmask1 */
void handler(int sig)
{
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0) /* Reap a zombie child */
deletejob(pid); /* Delete the child from the job list */
if (errno != ECHILD)
unix_error("waitpid error");
}
int main(int argc, char **argv)
{
int pid;
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
/* Child process */
if ((pid = Fork()) == 0) {
Execve("/bin/date", argv, NULL);
}
/* Parent process */
addjob(pid); /* Add the child to the job list */
}
exit(0);
}
/* $end procmask1 */
================================================
FILE: code/ecf/procmask2.c
================================================
#include "csapp.h"
void initjobs()
{
}
void addjob(int pid)
{
}
void deletejob(int pid)
{
}
/* $begin procmask2 */
void handler(int sig)
{
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0) /* Reap a zombie child */
deletejob(pid); /* Delete the child from the job list */
if (errno != ECHILD)
unix_error("waitpid error");
}
int main(int argc, char **argv)
{
int pid;
sigset_t mask;
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
Sigemptyset(&mask);
Sigaddset(&mask, SIGCHLD);
Sigprocmask(SIG_BLOCK, &mask, NULL); /* Block SIGCHLD */
/* Child process */
if ((pid = Fork()) == 0) {
Sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Unblock SIGCHLD */
Execve("/bin/date", argv, NULL);
}
/* Parent process */
addjob(pid); /* Add the child to the job list */
Sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Unblock SIGCHLD */
}
exit(0);
}
/* $end procmask2 */
================================================
FILE: code/ecf/restart.c
================================================
/* $begin restart */
#include "csapp.h"
sigjmp_buf buf;
void handler(int sig)
{
siglongjmp(buf, 1);
}
int main()
{
Signal(SIGINT, handler);
if (!sigsetjmp(buf, 1))
printf("starting\n");
else
printf("restarting\n");
while(1) {
Sleep(1);
printf("processing...\n");
}
exit(0);
}
/* $end restart */
================================================
FILE: code/ecf/rfork.c
================================================
/*
* rfork.c - Wrapper for fork() that introduces non-determinism
* in the order that the parent and child are executed
*/
/* $begin rfork */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
/* Sleep for a random period between [0, MAX_SLEEP] us */
#define MAX_SLEEP 100000
/* Macro that maps val into the range [0, RAND_MAX] */
#define CONVERT(val) (((double)val)/(double)RAND_MAX)
pid_t Fork(void)
{
static struct timeval time;
unsigned bool, secs;
pid_t pid;
/* Generate a different seed each time the function is called */
gettimeofday(&time, NULL);
srand(time.tv_usec);
/* Determine whether to sleep in parent of child and for how long */
bool = (unsigned)(CONVERT(rand()) + 0.5);
secs = (unsigned)(CONVERT(rand()) * MAX_SLEEP);
/* Call the real fork function */
if ((pid = fork()) < 0)
return pid;
/* Randomly decide to sleep in the parent or the child */
if (pid == 0) { /* Child */
if(bool) {
usleep(secs);
}
}
else { /* Parent */
if (!bool) {
usleep(secs);
}
}
/* Return the PID like a normal fork call */
return pid;
}
/* $end rfork */
================================================
FILE: code/ecf/setjmp.c
================================================
/* $begin setjmp */
#include "csapp.h"
jmp_buf buf;
int error1 = 0;
int error2 = 1;
void foo(void), bar(void);
int main()
{
int rc;
rc = setjmp(buf);
if (rc == 0)
foo();
else if (rc == 1)
printf("Detected an error1 condition in foo\n");
else if (rc == 2)
printf("Detected an error2 condition in foo\n");
else
printf("Unknown error condition in foo\n");
exit(0);
}
/* Deeply nested function foo */
void foo(void)
{
if (error1)
longjmp(buf, 1);
bar();
}
void bar(void)
{
if (error2)
longjmp(buf, 2);
}
/* $end setjmp */
================================================
FILE: code/ecf/shellex.c
================================================
/* $begin shellmain */
#include "csapp.h"
#define MAXARGS 128
/* function prototypes */
void eval(char *cmdline);
int parseline(char *buf, char **argv);
int builtin_command(char **argv);
int main()
{
char cmdline[MAXLINE]; /* Command line */
while (1) {
/* Read */
printf("> ");
Fgets(cmdline, MAXLINE, stdin);
if (feof(stdin))
exit(0);
/* Evaluate */
eval(cmdline);
}
}
/* $end shellmain */
/* $begin eval */
/* eval - Evaluate a command line */
void eval(char *cmdline)
{
char *argv[MAXARGS]; /* Argument list execve() */
char buf[MAXLINE]; /* Holds modified command line */
int bg; /* Should the job run in bg or fg? */
pid_t pid; /* Process id */
strcpy(buf, cmdline);
bg = parseline(buf, argv);
if (argv[0] == NULL)
return; /* Ignore empty lines */
if (!builtin_command(argv)) {
if ((pid = Fork()) == 0) { /* Child runs user job */
if (execve(argv[0], argv, environ) < 0) {
printf("%s: Command not found.\n", argv[0]);
exit(0);
}
}
/* Parent waits for foreground job to terminate */
if (!bg) {
int status;
if (waitpid(pid, &status, 0) < 0)
unix_error("waitfg: waitpid error");
}
else
printf("%d %s", pid, cmdline);
}
return;
}
/* If first arg is a builtin command, run it and return true */
int builtin_command(char **argv)
{
if (!strcmp(argv[0], "quit")) /* quit command */
exit(0);
if (!strcmp(argv[0], "&")) /* Ignore singleton & */
return 1;
return 0; /* Not a builtin command */
}
/* $end eval */
/* $begin parseline */
/* parseline - Parse the command line and build the argv array */
int parseline(char *buf, char **argv)
{
char *delim; /* Points to first space delimiter */
int argc; /* Number of args */
int bg; /* Background job? */
buf[strlen(buf)-1] = ' '; /* Replace trailing '\n' with space */
while (*buf && (*buf == ' ')) /* Ignore leading spaces */
buf++;
/* Build the argv list */
argc = 0;
while ((delim = strchr(buf, ' '))) {
argv[argc++] = buf;
*delim = '\0';
buf = delim + 1;
while (*buf && (*buf == ' ')) /* Ignore spaces */
buf++;
}
argv[argc] = NULL;
if (argc == 0) /* Ignore blank line */
return 1;
/* Should the job run in the background? */
if ((bg = (*argv[argc-1] == '&')) != 0)
argv[--argc] = NULL;
return bg;
}
/* $end parseline */
================================================
FILE: code/ecf/sigint1.c
================================================
/* $begin sigint1 */
#include "csapp.h"
void handler(int sig) /* SIGINT handler */ //line:ecf:sigint1:beginhandler
{
printf("Caught SIGINT\n"); //line:ecf:sigint1:printhandler
exit(0); //line:ecf:sigint1:exithandler
} //line:ecf:sigint1:endhandler
int main()
{
/* Install the SIGINT handler */
if (signal(SIGINT, handler) == SIG_ERR) //line:ecf:sigint1:begininstall
unix_error("signal error"); //line:ecf:sigint1:endinstall
pause(); /* Wait for the receipt of a signal */ //line:ecf:sigint1:pause
exit(0);
}
/* $end sigint1 */
================================================
FILE: code/ecf/signal1.c
================================================
/* $begin signal1 */
#include "csapp.h"
void handler1(int sig)
{
pid_t pid;
if ((pid = waitpid(-1, NULL, 0)) < 0)
unix_error("waitpid error");
printf("Handler reaped child %d\n", (int)pid);
Sleep(2);
return;
}
int main()
{
int i, n;
char buf[MAXBUF];
if (signal(SIGCHLD, handler1) == SIG_ERR)
unix_error("signal error");
/* Parent creates children */
for (i = 0; i < 3; i++) {
if (Fork() == 0) {
printf("Hello from child %d\n", (int)getpid());
Sleep(1);
exit(0);
}
}
/* Parent waits for terminal input and then processes it */
if ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)
unix_error("read");
printf("Parent processing input\n");
while (1)
;
exit(0);
}
/* $end signal1 */
================================================
FILE: code/ecf/signal2.c
================================================
/* $begin signal2 */
#include "csapp.h"
void handler2(int sig)
{
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0)
printf("Handler reaped child %d\n", (int)pid);
if (errno != ECHILD)
unix_error("waitpid error");
Sleep(2);
return;
}
int main()
{
int i, n;
char buf[MAXBUF];
if (signal(SIGCHLD, handler2) == SIG_ERR)
unix_error("signal error");
/* Parent creates children */
for (i = 0; i < 3; i++) {
if (Fork() == 0) {
printf("Hello from child %d\n", (int)getpid());
Sleep(1);
exit(0);
}
}
/* Parent waits for terminal input and then processes it */
if ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)
unix_error("read error");
printf("Parent processing input\n");
while (1)
;
exit(0);
}
/* $end signal2 */
================================================
FILE: code/ecf/signal3.c
================================================
/* $begin signal3 */
#include "csapp.h"
void handler2(int sig)
{
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0)
printf("Handler reaped child %d\n", (int)pid);
if (errno != ECHILD)
unix_error("waitpid error");
Sleep(2);
return;
}
int main() {
int i, n;
char buf[MAXBUF];
pid_t pid;
if (signal(SIGCHLD, handler2) == SIG_ERR)
unix_error("signal error");
/* Parent creates children */
for (i = 0; i < 3; i++) {
pid = Fork();
if (pid == 0) {
printf("Hello from child %d\n", (int)getpid());
Sleep(1);
exit(0);
}
}
/* Manually restart the read call if it is interrupted */
while ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)
if (errno != EINTR)
unix_error("read error");
printf("Parent processing input\n");
while (1)
;
exit(0);
}
/* $end signal3 */
================================================
FILE: code/ecf/signal4.c
================================================
/* $begin signal4 */
#include "csapp.h"
void handler2(int sig)
{
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0)
printf("Handler reaped child %d\n", (int)pid);
if (errno != ECHILD)
unix_error("waitpid error");
Sleep(2);
return;
}
int main()
{
int i, n;
char buf[MAXBUF];
pid_t pid;
Signal(SIGCHLD, handler2); /* sigaction error-handling wrapper */
/* Parent creates children */
for (i = 0; i < 3; i++) {
pid = Fork();
if (pid == 0) {
printf("Hello from child %d\n", (int)getpid());
Sleep(1);
exit(0);
}
}
/* Parent waits for terminal input and then processes it */
if ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)
unix_error("read error");
printf("Parent processing input\n");
while (1)
;
exit(0);
}
/* $end signal4 */
================================================
FILE: code/ecf/signalprob0.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
/* $begin signalprob0 */
pid_t pid;
int counter = 2;
void handler1(int sig) {
counter = counter - 1;
printf("%d", counter);
fflush(stdout);
exit(0);
}
int main() {
signal(SIGUSR1, handler1);
printf("%d", counter);
fflush(stdout);
if ((pid = fork()) == 0) {
while(1) {};
}
kill(pid, SIGUSR1);
waitpid(-1, NULL, 0);
counter = counter + 1;
printf("%d", counter);
exit(0);
}
/* $end signalprob0 */
================================================
FILE: code/ecf/waitpid1.c
================================================
/* $begin waitpid1 */
#include "csapp.h"
#define N 2
int main()
{
int status, i;
pid_t pid;
/* Parent creates N children */
for (i = 0; i < N; i++) //line:ecf:waitpid1:for
if ((pid = Fork()) == 0) /* child */ //line:ecf:waitpid1:fork
exit(100+i); //line:ecf:waitpid1:exit
/* Parent reaps N children in no particular order */
while ((pid = waitpid(-1, &status, 0)) > 0) { //line:ecf:waitpid1:waitpid
if (WIFEXITED(status)) //line:ecf:waitpid1:wifexited
printf("child %d terminated normally with exit status=%d\n",
pid, WEXITSTATUS(status)); //line:ecf:waitpid1:wexitstatus
else
printf("child %d terminated abnormally\n", pid);
}
/* The only normal termination is if there are no more children */
if (errno != ECHILD) //line:ecf:waitpid1:errno
unix_error("waitpid error");
exit(0);
}
/* $end waitpid1 */
================================================
FILE: code/ecf/waitpid2.c
================================================
/* $begin waitpid2 */
#include "csapp.h"
#define N 2
int main()
{
int status, i;
pid_t pid[N], retpid;
/* Parent creates N children */
for (i = 0; i < N; i++)
if ((pid[i] = Fork()) == 0) /* Child */ //line:ecf:waitpid2:fork
exit(100+i);
/* Parent reaps N children in order */
i = 0;
while ((retpid = waitpid(pid[i++], &status, 0)) > 0) { //line:ecf:waitpid2:waitpid
if (WIFEXITED(status))
printf("child %d terminated normally with exit status=%d\n",
retpid, WEXITSTATUS(status));
else
printf("child %d terminated abnormally\n", retpid);
}
/* The only normal termination is if there are no more children */
if (errno != ECHILD)
unix_error("waitpid error");
exit(0);
}
/* $end waitpid2 */
================================================
FILE: code/ecf/waitprob0.c
================================================
#include "csapp.h"
/* $begin waitprob0 */
int main()
{
if (Fork() == 0) {
printf("a");
}
else {
printf("b");
waitpid(-1, NULL, 0);
}
printf("c");
exit(0);
}
/* $end waitprob0 */
================================================
FILE: code/ecf/waitprob1.c
================================================
#include "csapp.h"
/* $begin waitprob1 */
int main()
{
int status;
pid_t pid;
printf("Hello\n");
pid = Fork();
printf("%d\n", !pid);
if (pid != 0) {
if (waitpid(-1, &status, 0) > 0) {
if (WIFEXITED(status) != 0)
printf("%d\n", WEXITSTATUS(status));
}
}
printf("Bye\n");
exit(2);
}
/* $end waitprob1 */
================================================
FILE: code/ecf/waitprob3.c
================================================
#include "csapp.h"
/* $begin waitprob3 */
int main()
{
if (fork() == 0) {
printf("a");
exit(0);
}
else {
printf("b");
waitpid(-1, NULL, 0);
}
printf("c");
exit(0);
}
/* $end waitprob3 */
================================================
FILE: code/include/csapp.h
================================================
/* $begin csapp.h */
#ifndef __CSAPP_H__
#define __CSAPP_H__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* Default file permissions are DEF_MODE & ~DEF_UMASK */
/* $begin createmasks */
#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
#define DEF_UMASK S_IWGRP|S_IWOTH
/* $end createmasks */
/* Simplifies calls to bind(), connect(), and accept() */
/* $begin sockaddrdef */
typedef struct sockaddr SA;
/* $end sockaddrdef */
/* Persistent state for the robust I/O (Rio) package */
/* $begin rio_t */
#define RIO_BUFSIZE 8192
typedef struct {
int rio_fd; /* descriptor for this internal buf */
int rio_cnt; /* unread bytes in internal buf */
char *rio_bufptr; /* next unread byte in internal buf */
char rio_buf[RIO_BUFSIZE]; /* internal buffer */
} rio_t;
/* $end rio_t */
/* External variables */
extern int h_errno; /* defined by BIND for DNS errors */
extern char **environ; /* defined by libc */
/* Misc constants */
#define MAXLINE 8192 /* max text line length */
#define MAXBUF 8192 /* max I/O buffer size */
#define LISTENQ 1024 /* second argument to listen() */
/* Our own error-handling functions */
void unix_error(char *msg);
void posix_error(int code, char *msg);
void dns_error(char *msg);
void app_error(char *msg);
/* Process control wrappers */
pid_t Fork(void);
void Execve(const char *filename, char *const argv[], char *const envp[]);
pid_t Wait(int *status);
pid_t Waitpid(pid_t pid, int *iptr, int options);
void Kill(pid_t pid, int signum);
unsigned int Sleep(unsigned int secs);
void Pause(void);
unsigned int Alarm(unsigned int seconds);
void Setpgid(pid_t pid, pid_t pgid);
pid_t Getpgrp();
/* Signal wrappers */
typedef void handler_t(int);
handler_t *Signal(int signum, handler_t *handler);
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
void Sigemptyset(sigset_t *set);
void Sigfillset(sigset_t *set);
void Sigaddset(sigset_t *set, int signum);
void Sigdelset(sigset_t *set, int signum);
int Sigismember(const sigset_t *set, int signum);
/* Unix I/O wrappers */
int Open(const char *pathname, int flags, mode_t mode);
ssize_t Read(int fd, void *buf, size_t count);
ssize_t Write(int fd, const void *buf, size_t count);
off_t Lseek(int fildes, off_t offset, int whence);
void Close(int fd);
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
int Dup2(int fd1, int fd2);
void Stat(const char *filename, struct stat *buf);
void Fstat(int fd, struct stat *buf) ;
/* Memory mapping wrappers */
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
void Munmap(void *start, size_t length);
/* Standard I/O wrappers */
void Fclose(FILE *fp);
FILE *Fdopen(int fd, const char *type);
char *Fgets(char *ptr, int n, FILE *stream);
FILE *Fopen(const char *filename, const char *mode);
void Fputs(const char *ptr, FILE *stream);
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
/* Dynamic storage allocation wrappers */
void *Malloc(size_t size);
void *Realloc(void *ptr, size_t size);
void *Calloc(size_t nmemb, size_t size);
void Free(void *ptr);
/* Sockets interface wrappers */
int Socket(int domain, int type, int protocol);
void Setsockopt(int s, int level, int optname, const void *optval, int optlen);
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen);
void Listen(int s, int backlog);
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
/* DNS wrappers */
struct hostent *Gethostbyname(const char *name);
struct hostent *Gethostbyaddr(const char *addr, int len, int type);
/* Pthreads thread control wrappers */
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void * (*routine)(void *), void *argp);
void Pthread_join(pthread_t tid, void **thread_return);
void Pthread_cancel(pthread_t tid);
void Pthread_detach(pthread_t tid);
void Pthread_exit(void *retval);
pthread_t Pthread_self(void);
void Pthread_once(pthread_once_t *once_control, void (*init_function)());
/* POSIX semaphore wrappers */
void Sem_init(sem_t *sem, int pshared, unsigned int value);
void P(sem_t *sem);
void V(sem_t *sem);
/* Rio (Robust I/O) package */
ssize_t rio_readn(int fd, void *usrbuf, size_t n);
ssize_t rio_writen(int fd, void *usrbuf, size_t n);
void rio_readinitb(rio_t *rp, int fd);
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
/* Wrappers for Rio package */
ssize_t Rio_readn(int fd, void *usrbuf, size_t n);
void Rio_writen(int fd, void *usrbuf, size_t n);
void Rio_readinitb(rio_t *rp, int fd);
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
/* Client/server helper functions */
int open_clientfd(char *hostname, int portno);
int open_listenfd(int portno);
/* Wrappers for client/server helper functions */
int Open_clientfd(char *hostname, int port);
int Open_listenfd(int port);
#endif /* __CSAPP_H__ */
/* $end csapp.h */
================================================
FILE: code/intro/hello.c
================================================
/* $begin hello */
#include <stdio.h>
int main()
{
printf("hello, world\n");
}
/* $end hello */
================================================
FILE: code/io/cpfile.c
================================================
/* $begin cpfile */
#include "csapp.h"
int main(int argc, char **argv)
{
int n;
rio_t rio;
char buf[MAXLINE];
Rio_readinitb(&rio, STDIN_FILENO);
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0)
Rio_writen(STDOUT_FILENO, buf, n);
/* $end cpfile */
exit(0);
/* $begin cpfile */
}
/* $end cpfile */
================================================
FILE: code/io/cpstdin.c
================================================
/* $begin cpstdin */
#include "csapp.h"
int main(void)
{
char c;
while(Read(STDIN_FILENO, &c, 1) != 0)
Write(STDOUT_FILENO, &c, 1);
exit(0);
}
/* $end cpstdin */
================================================
FILE: code/io/statcheck.c
================================================
/* $begin statcheck */
#include "csapp.h"
int main (int argc, char **argv)
{
struct stat stat;
char *type, *readok;
/* $end statcheck */
if (argc != 2) {
fprintf(stderr, "usage: %s <filename>\n", argv[0]);
exit(0);
}
/* $begin statcheck */
Stat(argv[1], &stat);
if (S_ISREG(stat.st_mode)) /* Determine file type */
type = "regular";
else if (S_ISDIR(stat.st_mode))
type = "directory";
else
type = "other";
if ((stat.st_mode & S_IRUSR)) /* Check read access */
readok = "yes";
else
readok = "no";
printf("type: %s, read: %s\n", type, readok);
exit(0);
}
/* $end statcheck */
================================================
FILE: code/link/addvec.c
================================================
/* addvec.c */
/* $begin addvec */
void addvec(int *x, int *y,
int *z, int n)
{
int i;
for (i = 0; i < n; i++)
z[i] = x[i] + y[i];
}
/* $end addvec */
================================================
FILE: code/link/dll.c
================================================
/* $begin dll */
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];
int main()
{
void *handle;
void (*addvec)(int *, int *, int *, int);
char *error;
/* dynamically load the shared library that contains addvec() */
handle = dlopen("./libvector.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
/* get a pointer to the addvec() function we just loaded */
addvec = dlsym(handle, "addvec");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
/* Now we can call addvec() it just like any other function */
addvec(x, y, z, 2);
printf("z = [%d %d]\n", z[0], z[1]);
/* unload the shared library */
if (dlclose(handle) < 0) {
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
return 0;
}
/* $end dll */
================================================
FILE: code/link/elfstructs.c
================================================
/* $begin elfsymbol */
typedef struct {
int name; /* string table offset */
int value; /* section offset, or VM address */
int size; /* object size in bytes */
char type:4, /* data, func, section, or src file name (4 bits) */
binding:4; /* local or global (4 bits) */
char reserved; /* unused */
char section; /* section header index, ABS, UNDEF, */
/* or COMMON */
} Elf_Symbol;
/* $end elfsymbol */
/* $begin elfrelo */
typedef struct {
int offset; /* offset of the reference to relocate */
int symbol:24, /* symbol the reference should point to */
type:8; /* relocation type */
} Elf32_Rel;
/* $end elfrelo */
================================================
FILE: code/link/main.c
================================================
/* $begin main */
/* main.c */
void swap();
int buf[2] = {1, 2};
int main()
{
swap();
return 0;
}
/* $end main */
================================================
FILE: code/link/main2.c
================================================
/* $begin main2 */
/* main2.c */
#include <stdio.h>
#include "vector.h"
int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];
int main()
{
addvec(x, y, z, 2);
printf("z = [%d %d]\n", z[0], z[1]);
return 0;
}
/* $end main2 */
================================================
FILE: code/link/multvec.c
================================================
/* multvec.c */
/* $begin multvec */
void multvec(int *x, int *y,
int *z, int n)
{
int i;
for (i = 0; i < n; i++)
z[i] = x[i] * y[i];
}
/* $end multvec */
================================================
FILE: code/link/p-exe.d
================================================
p: file format elf32-i386
p
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080482f0
Program Header:
PHDR off 0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
filesz 0x000000c0 memsz 0x000000c0 flags r-x
INTERP off 0x000000f4 vaddr 0x080480f4 paddr 0x080480f4 align 2**0
filesz 0x00000013 memsz 0x00000013 flags r--
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x00000448 memsz 0x00000448 flags r-x
LOAD off 0x00000448 vaddr 0x08049448 paddr 0x08049448 align 2**12
filesz 0x000000e8 memsz 0x00000104 flags rw-
DYNAMIC off 0x00000490 vaddr 0x08049490 paddr 0x08049490 align 2**2
filesz 0x000000a0 memsz 0x000000a0 flags rw-
NOTE off 0x00000108 vaddr 0x08048108 paddr 0x08048108 align 2**2
filesz 0x00000020 memsz 0x00000020 flags r--
Dynamic Section:
NEEDED libc.so.6
INIT 0x8048274
FINI 0x8048424
HASH 0x8048128
STRTAB 0x80481b4
SYMTAB 0x8048154
STRSZ 0x69
SYMENT 0x10
DEBUG 0x0
PLTGOT 0x8049474
PLTRELSZ 0x18
PLTREL 0x11
JMPREL 0x804825c
REL 0x8048254
RELSZ 0x8
RELENT 0x8
VERNEED 0x8048234
VERNEEDNUM 0x1
VERSYM 0x8048228
Version References:
required from libc.so.6:
0x0d696910 0x00 02 GLIBC_2.0
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 080480f4 080480f4 000000f4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048108 08048108 00000108 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .hash 0000002c 08048128 08048128 00000128 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynsym 00000060 08048154 08048154 00000154 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynstr 00000073 080481b4 080481b4 000001b4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version 0000000c 08048228 08048228 00000228 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version_r 00000020 08048234 08048234 00000234 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.got 00000008 08048254 08048254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.plt 00000018 0804825c 0804825c 0000025c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .init 0000002f 08048274 08048274 00000274 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .plt 00000040 080482a4 080482a4 000002a4 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .text 00000134 080482f0 080482f0 000002f0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .fini 0000001a 08048424 08048424 00000424 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .rodata 00000008 08048440 08048440 00000440 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
14 .data 00000018 08049448 08049448 00000448 2**2
CONTENTS, ALLOC, LOAD, DATA
15 .eh_frame 00000004 08049460 08049460 00000460 2**2
CONTENTS, ALLOC, LOAD, DATA
16 .ctors 00000008 08049464 08049464 00000464 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .dtors 00000008 0804946c 0804946c 0000046c 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .got 0000001c 08049474 08049474 00000474 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .dynamic 000000a0 08049490 08049490 00000490 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .bss 0000001c 08049530 08049530 00000530 2**2
ALLOC
21 .stab 00000750 00000000 00000000 00000530 2**2
CONTENTS, READONLY, DEBUGGING
22 .stabstr 0000134f 00000000 00000000 00000c80 2**0
CONTENTS, READONLY, DEBUGGING
23 .comment 0000014f 00000000 00000000 00001fcf 2**0
CONTENTS, READONLY
24 .note 0000008c 0804954c 0804954c 0000211e 2**0
CONTENTS, READONLY
SYMBOL TABLE:
080480f4 l d .interp 00000000
08048108 l d .note.ABI-tag 00000000
08048128 l d .hash 00000000
08048154 l d .dynsym 00000000
080481b4 l d .dynstr 00000000
08048228 l d .gnu.version 00000000
08048234 l d .gnu.version_r 00000000
08048254 l d .rel.got 00000000
0804825c l d .rel.plt 00000000
08048274 l d .init 00000000
080482a4 l d .plt 00000000
080482f0 l d .text 00000000
08048424 l d .fini 00000000
08048440 l d .rodata 00000000
08049448 l d .data 00000000
08049460 l d .eh_frame 00000000
08049464 l d .ctors 00000000
0804946c l d .dtors 00000000
08049474 l d .got 00000000
08049490 l d .dynamic 00000000
08049530 l d .bss 00000000
00000000 l d .stab 00000000
00000000 l d .stabstr 00000000
00000000 l d .comment 00000000
0804954c l d .note 00000000
00000000 l d *ABS* 00000000
00000000 l d *ABS* 00000000
00000000 l d *ABS* 00000000
00000000 l df *ABS* 00000000 initfini.c
08048314 l .text 00000000 gcc2_compiled.
00000000 l df *ABS* 00000000 init.c
00000000 l df *ABS* 00000000 crtstuff.c
08048320 l .text 00000000 gcc2_compiled.
0804944c l O .data 00000000 p.3
0804946c l O .dtors 00000000 __DTOR_LIST__
08049450 l O .data 00000000 completed.4
08048320 l F .text 00000000 __do_global_dtors_aux
08049460 l O .eh_frame 00000000 __EH_FRAME_BEGIN__
08048374 l F .text 00000000 fini_dummy
08049530 l O .bss 00000018 object.11
08048380 l F .text 00000000 frame_dummy
080483a8 l F .text 00000000 init_dummy
08049454 l O .data 00000000 force_to_data
08049464 l O .ctors 00000000 __CTOR_LIST__
00000000 l df *ABS* 00000000 crtstuff.c
080483f0 l .text 00000000 gcc2_compiled.
080483f0 l F .text 00000000 __do_global_ctors_aux
08049468 l O .ctors 00000000 __CTOR_END__
08048418 l F .text 00000000 init_dummy
08049460 l O .data 00000000 force_to_data
08049470 l O .dtors 00000000 __DTOR_END__
08049460 l O .eh_frame 00000000 __FRAME_END__
00000000 l df *ABS* 00000000 initfini.c
08048424 l .text 00000000 gcc2_compiled.
00000000 l df *ABS* 00000000 main.c
080483b4 l .text 00000000 gcc2_compiled.
00000000 l df *ABS* 00000000 swap.c
080483c8 l .text 00000000 gcc2_compiled.
0804945c g O .data 00000004 bufp0
08049490 g O .dynamic 00000000 _DYNAMIC
08048424 g O *ABS* 00000000 _etext
080482b4 w F *UND* 00000074 __register_frame_info@@GLIBC_2.0
00000000 *UND* 00000004 _fp_hw
080483c8 g F .text 00000027 swap
08048274 g F .init 00000000 _init
080482c4 w F *UND* 000000a2 __deregister_frame_info@@GLIBC_2.0
080482f0 g .text 00000000 _start
08049530 g O *ABS* 00000000 __bss_start
080483b4 g F .text 00000011 main
080482d4 F *UND* 00000105 __libc_start_main@@GLIBC_2.0
08049448 w .data 00000000 data_start
08048424 g F .fini 00000000 _fini
08049454 g O .data 00000008 buf
08049530 g O *ABS* 00000000 _edata
08049474 g O .got 00000000 _GLOBAL_OFFSET_TABLE_
0804954c g O *ABS* 00000000 _end
08048444 g O .rodata 00000004 _IO_stdin_used
08049448 g .data 00000000 __data_start
08049548 g O .bss 00000004 bufp1
00000000 w *UND* 00000000 __gmon_start__
Disassembly of section .init:
08048274 <_init>:
8048274: 55 push %ebp
8048275: 89 e5 mov %esp,%ebp
8048277: 53 push %ebx
8048278: e8 00 00 00 00 call 804827d <_init+0x9>
804827d: 5b pop %ebx
804827e: 81 c3 f7 11 00 00 add $0x11f7,%ebx
8048284: 83 bb 18 00 00 00 00 cmpl $0x0,0x18(%ebx)
804828b: 74 05 je 8048292 <_init+0x1e>
804828d: e8 6e 7d fb f7 call 0 <_init-0x8048274>
8048292: 89 f6 mov %esi,%esi
8048294: e8 e7 00 00 00 call 8048380 <frame_dummy>
8048299: e8 52 01 00 00 call 80483f0 <__do_global_ctors_aux>
804829e: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80482a1: c9 leave
80482a2: c3 ret
Disassembly of section .plt:
080482a4 <.plt>:
80482a4: ff 35 78 94 04 08 pushl 0x8049478
80482aa: ff 25 7c 94 04 08 jmp *0x804947c
80482b0: 00 00 add %al,(%eax)
80482b2: 00 00 add %al,(%eax)
80482b4: ff 25 80 94 04 08 jmp *0x8049480
80482ba: 68 00 00 00 00 push $0x0
80482bf: e9 e0 ff ff ff jmp 80482a4 <_init+0x30>
80482c4: ff 25 84 94 04 08 jmp *0x8049484
80482ca: 68 08 00 00 00 push $0x8
80482cf: e9 d0 ff ff ff jmp 80482a4 <_init+0x30>
80482d4: ff 25 88 94 04 08 jmp *0x8049488
80482da: 68 10 00 00 00 push $0x10
80482df: e9 c0 ff ff ff jmp 80482a4 <_init+0x30>
Disassembly of section .text:
080482f0 <_start>:
80482f0: 31 ed xor %ebp,%ebp
80482f2: 5e pop %esi
80482f3: 89 e1 mov %esp,%ecx
80482f5: 83 e4 f8 and $0xfffffff8,%esp
80482f8: 50 push %eax
80482f9: 54 push %esp
80482fa: 52 push %edx
80482fb: 68 24 84 04 08 push $0x8048424
8048300: 68 74 82 04 08 push $0x8048274
8048305: 51 push %ecx
8048306: 56 push %esi
8048307: 68 b4 83 04 08 push $0x80483b4
804830c: e8 c3 ff ff ff call 80482d4 <_init+0x60>
8048311: f4 hlt
8048312: 90 nop
8048313: 90 nop
08048314 <gcc2_compiled.>:
8048314: 90 90 90 90 90 90 90 90 90 90 90 90 ............
08048320 <__do_global_dtors_aux>:
8048320: 55 push %ebp
8048321: 89 e5 mov %esp,%ebp
8048323: 83 ec 08 sub $0x8,%esp
8048326: 83 3d 50 94 04 08 00 cmpl $0x0,0x8049450
804832d: 75 3e jne 804836d <__do_global_dtors_aux+0x4d>
804832f: eb 12 jmp 8048343 <__do_global_dtors_aux+0x23>
8048331: a1 4c 94 04 08 mov 0x804944c,%eax
8048336: 8d 50 04 lea 0x4(%eax),%edx
8048339: 89 15 4c 94 04 08 mov %edx,0x804944c
804833f: 8b 00 mov (%eax),%eax
8048341: ff d0 call *%eax
8048343: a1 4c 94 04 08 mov 0x804944c,%eax
8048348: 83 38 00 cmpl $0x0,(%eax)
804834b: 75 e4 jne 8048331 <__do_global_dtors_aux+0x11>
804834d: b8 c4 82 04 08 mov $0x80482c4,%eax
8048352: 85 c0 test %eax,%eax
8048354: 74 0d je 8048363 <__do_global_dtors_aux+0x43>
8048356: 83 c4 f4 add $0xfffffff4,%esp
8048359: 68 60 94 04 08 push $0x8049460
804835e: e8 61 ff ff ff call 80482c4 <_init+0x50>
8048363: c7 05 50 94 04 08 01 movl $0x1,0x8049450
804836a: 00 00 00
804836d: 89 ec mov %ebp,%esp
804836f: 5d pop %ebp
8048370: c3 ret
8048371: 8d 76 00 lea 0x0(%esi),%esi
08048374 <fini_dummy>:
8048374: 55 push %ebp
8048375: 89 e5 mov %esp,%ebp
8048377: 83 ec 08 sub $0x8,%esp
804837a: 89 ec mov %ebp,%esp
804837c: 5d pop %ebp
804837d: c3 ret
804837e: 89 f6 mov %esi,%esi
08048380 <frame_dummy>:
8048380: 55 push %ebp
8048381: 89 e5 mov %esp,%ebp
8048383: 83 ec 08 sub $0x8,%esp
8048386: b8 b4 82 04 08 mov $0x80482b4,%eax
804838b: 85 c0 test %eax,%eax
804838d: 74 12 je 80483a1 <frame_dummy+0x21>
804838f: 83 c4 f8 add $0xfffffff8,%esp
8048392: 68 30 95 04 08 push $0x8049530
8048397: 68 60 94 04 08 push $0x8049460
804839c: e8 13 ff ff ff call 80482b4 <_init+0x40>
80483a1: 89 ec mov %ebp,%esp
80483a3: 5d pop %ebp
80483a4: c3 ret
80483a5: 8d 76 00 lea 0x0(%esi),%esi
080483a8 <init_dummy>:
80483a8: 55 push %ebp
80483a9: 89 e5 mov %esp,%ebp
80483ab: 83 ec 08 sub $0x8,%esp
80483ae: 89 ec mov %ebp,%esp
80483b0: 5d pop %ebp
80483b1: c3 ret
80483b2: 90 nop
80483b3: 90 nop
080483b4 <main>:
80483b4: 55 push %ebp
80483b5: 89 e5 mov %esp,%ebp
80483b7: 83 ec 08 sub $0x8,%esp
80483ba: e8 09 00 00 00 call 80483c8 <swap>
80483bf: 31 c0 xor %eax,%eax
80483c1: 89 ec mov %ebp,%esp
80483c3: 5d pop %ebp
80483c4: c3 ret
80483c5: 90 nop
80483c6: 90 nop
80483c7: 90 nop
080483c8 <swap>:
80483c8: 55 push %ebp
80483c9: 8b 15 5c 94 04 08 mov 0x804945c,%edx
80483cf: a1 58 94 04 08 mov 0x8049458,%eax
80483d4: 89 e5 mov %esp,%ebp
80483d6: c7 05 48 95 04 08 58 movl $0x8049458,0x8049548
80483dd: 94 04 08
80483e0: 89 ec mov %ebp,%esp
80483e2: 8b 0a mov (%edx),%ecx
80483e4: 89 02 mov %eax,(%edx)
80483e6: a1 48 95 04 08 mov 0x8049548,%eax
80483eb: 89 08 mov %ecx,(%eax)
80483ed: 5d pop %ebp
80483ee: c3 ret
80483ef: 90 nop
080483f0 <__do_global_ctors_aux>:
80483f0: 55 push %ebp
80483f1: 89 e5 mov %esp,%ebp
80483f3: 83 ec 14 sub $0x14,%esp
80483f6: 53 push %ebx
80483f7: bb 64 94 04 08 mov $0x8049464,%ebx
80483fc: 83 3d 64 94 04 08 ff cmpl $0xffffffff,0x8049464
8048403: 74 0c je 8048411 <__do_global_ctors_aux+0x21>
8048405: 8b 03 mov (%ebx),%eax
8048407: ff d0 call *%eax
8048409: 83 c3 fc add $0xfffffffc,%ebx
804840c: 83 3b ff cmpl $0xffffffff,(%ebx)
804840f: 75 f4 jne 8048405 <__do_global_ctors_aux+0x15>
8048411: 5b pop %ebx
8048412: 89 ec mov %ebp,%esp
8048414: 5d pop %ebp
8048415: c3 ret
8048416: 89 f6 mov %esi,%esi
08048418 <init_dummy>:
8048418: 55 push %ebp
8048419: 89 e5 mov %esp,%ebp
804841b: 83 ec 08 sub $0x8,%esp
804841e: 89 ec mov %ebp,%esp
8048420: 5d pop %ebp
8048421: c3 ret
8048422: 90 nop
8048423: 90 nop
Disassembly of section .fini:
08048424 <_fini>:
8048424: 55 push %ebp
8048425: 89 e5 mov %esp,%ebp
8048427: 53 push %ebx
8048428: e8 00 00 00 00 call 804842d <_etext+0x9>
804842d: 5b pop %ebx
804842e: 81 c3 47 10 00 00 add $0x1047,%ebx
8048434: e8 e7 fe ff ff call 8048320 <__do_global_dtors_aux>
8048439: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
804843c: c9 leave
804843d: c3 ret
================================================
FILE: code/link/pdata-exe.d
================================================
p: file format elf32-i386
p
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080482f0
Program Header:
PHDR off 0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
filesz 0x000000c0 memsz 0x000000c0 flags r-x
INTERP off 0x000000f4 vaddr 0x080480f4 paddr 0x080480f4 align 2**0
filesz 0x00000013 memsz 0x00000013 flags r--
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x00000448 memsz 0x00000448 flags r-x
LOAD off 0x00000448 vaddr 0x08049448 paddr 0x08049448 align 2**12
filesz 0x000000e8 memsz 0x00000104 flags rw-
DYNAMIC off 0x00000490 vaddr 0x08049490 paddr 0x08049490 align 2**2
filesz 0x000000a0 memsz 0x000000a0 flags rw-
NOTE off 0x00000108 vaddr 0x08048108 paddr 0x08048108 align 2**2
filesz 0x00000020 memsz 0x00000020 flags r--
Dynamic Section:
NEEDED libc.so.6
INIT 0x8048274
FINI 0x8048424
HASH 0x8048128
STRTAB 0x80481b4
SYMTAB 0x8048154
STRSZ 0x69
SYMENT 0x10
DEBUG 0x0
PLTGOT 0x8049474
PLTRELSZ 0x18
PLTREL 0x11
JMPREL 0x804825c
REL 0x8048254
RELSZ 0x8
RELENT 0x8
VERNEED 0x8048234
VERNEEDNUM 0x1
VERSYM 0x8048228
Version References:
required from libc.so.6:
0x0d696910 0x00 02 GLIBC_2.0
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 080480f4 080480f4 000000f4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048108 08048108 00000108 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .hash 0000002c 08048128 08048128 00000128 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynsym 00000060 08048154 08048154 00000154 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynstr 00000073 080481b4 080481b4 000001b4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version 0000000c 08048228 08048228 00000228 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version_r 00000020 08048234 08048234 00000234 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.got 00000008 08048254 08048254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.plt 00000018 0804825c 0804825c 0000025c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .init 0000002f 08048274 08048274 00000274 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .plt 00000040 080482a4 080482a4 000002a4 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .text 00000134 080482f0 080482f0 000002f0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .fini 0000001a 08048424 08048424 00000424 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .rodata 00000008 08048440 08048440 00000440 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
14 .data 00000018 08049448 08049448 00000448 2**2
CONTENTS, ALLOC, LOAD, DATA
15 .eh_frame 00000004 08049460 08049460 00000460 2**2
CONTENTS, ALLOC, LOAD, DATA
16 .ctors 00000008 08049464 08049464 00000464 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .dtors 00000008 0804946c 0804946c 0000046c 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .got 0000001c 08049474 08049474 00000474 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .dynamic 000000a0 08049490 08049490 00000490 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .bss 0000001c 08049530 08049530 00000530 2**2
ALLOC
21 .stab 00000750 00000000 00000000 00000530 2**2
CONTENTS, READONLY, DEBUGGING
22 .stabstr 0000134f 00000000 00000000 00000c80 2**0
CONTENTS, READONLY, DEBUGGING
23 .comment 0000014f 00000000 00000000 00001fcf 2**0
CONTENTS, READONLY
24 .note 0000008c 0804954c 0804954c 0000211e 2**0
CONTENTS, READONLY
SYMBOL TABLE:
080480f4 l d .interp 00000000
08048108 l d .note.ABI-tag 00000000
08048128 l d .hash 00000000
08048154 l d .dynsym 00000000
080481b4 l d .dynstr 00000000
08048228 l d .gnu.version 00000000
08048234 l d .gnu.version_r 00000000
08048254 l d .rel.got 00000000
0804825c l d .rel.plt 00000000
08048274 l d .init 00000000
080482a4 l d .plt 00000000
080482f0 l d .text 00000000
08048424 l d .fini 00000000
08048440 l d .rodata 00000000
08049448 l d .data 00000000
08049460 l d .eh_frame 00000000
08049464 l d .ctors 00000000
0804946c l d .dtors 00000000
08049474 l d .got 00000000
08049490 l d .dynamic 00000000
08049530 l d .bss 00000000
00000000 l d .stab 00000000
00000000 l d .stabstr 00000000
00000000 l d .comment 00000000
0804954c l d .note 00000000
00000000 l d *ABS* 00000000
00000000 l d *ABS* 00000000
00000000 l d *ABS* 00000000
00000000 l df *ABS* 00000000 initfini.c
08048314 l .text 00000000 gcc2_compiled.
00000000 l df *ABS* 00000000 init.c
00000000 l df *ABS* 00000000 crtstuff.c
08048320 l .text 00000000 gcc2_compiled.
0804944c l O .data 00000000 p.3
0804946c l O .dtors 00000000 __DTOR_LIST__
08049450 l O .data 00000000 completed.4
08048320 l F .text 00000000 __do_global_dtors_aux
08049460 l O .eh_frame 00000000 __EH_FRAME_BEGIN__
08048374 l F .text 00000000 fini_dummy
08049530 l O .bss 00000018 object.11
08048380 l F .text 00000000 frame_dummy
080483a8 l F .text 00000000 init_dummy
08049454 l O .data 00000000 force_to_data
08049464 l O .ctors 00000000 __CTOR_LIST__
00000000 l df *ABS* 00000000 crtstuff.c
080483f0 l .text 00000000 gcc2_compiled.
080483f0 l F .text 00000000 __do_global_ctors_aux
08049468 l O .ctors 00000000 __CTOR_END__
08048418 l F .text 00000000 init_dummy
08049460 l O .data 00000000 force_to_data
08049470 l O .dtors 00000000 __DTOR_END__
08049460 l O .eh_frame 00000000 __FRAME_END__
00000000 l df *ABS* 00000000 initfini.c
08048424 l .text 00000000 gcc2_compiled.
00000000 l df *ABS* 00000000 main.c
080483b4 l .text 00000000 gcc2_compiled.
00000000 l df *ABS* 00000000 swap.c
080483c8 l .text 00000000 gcc2_compiled.
0804945c g O .data 00000004 bufp0
08049490 g O .dynamic 00000000 _DYNAMIC
08048424 g O *ABS* 00000000 _etext
080482b4 w F *UND* 00000074 __register_frame_info@@GLIBC_2.0
00000000 *UND* 00000004 _fp_hw
080483c8 g F .text 00000027 swap
08048274 g F .init 00000000 _init
080482c4 w F *UND* 000000a2 __deregister_frame_info@@GLIBC_2.0
080482f0 g .text 00000000 _start
08049530 g O *ABS* 00000000 __bss_start
080483b4 g F .text 00000011 main
080482d4 F *UND* 00000105 __libc_start_main@@GLIBC_2.0
08049448 w .data 00000000 data_start
08048424 g F .fini 00000000 _fini
08049454 g O .data 00000008 buf
08049530 g O *ABS* 00000000 _edata
08049474 g O .got 00000000 _GLOBAL_OFFSET_TABLE_
0804954c g O *ABS* 00000000 _end
08048444 g O .rodata 00000004 _IO_stdin_used
08049448 g .data 00000000 __data_start
08049548 g O .bss 00000004 bufp1
00000000 w *UND* 00000000 __gmon_start__
Disassembly of section .data:
08049448 <__data_start>:
8049448: 00 00 add %al,(%eax)
...
0804944c <p.3>:
804944c: 70 94 04 08 p...
08049450 <completed.4>:
8049450: 00 00 00 00 ....
08049454 <buf>:
8049454: 01 00 00 00 02 00 00 00 ........
0804945c <bufp0>:
804945c: 54 94 04 08 T...
================================================
FILE: code/link/swap.c
================================================
/* $begin swap */
/* swap.c */
extern int buf[];
int *bufp0 = &buf[0];
int *bufp1;
void swap()
{
int temp;
bufp1 = &buf[1];
temp = *bufp0;
*bufp0 = *bufp1;
*bufp1 = temp;
}
/* $end swap */
================================================
FILE: code/mem/matmult/mm.c
================================================
/* matrix multiply permutations */
#include <stdio.h>
#include <stdlib.h>
#include "mm.h"
#include "fcycmm.h"
#include "clock.h"
/* whether or not fcyc should clear the cache */
#define CLEARCACHE 0
/* global arrays */
array ga, gb, gc;
/* check the result array for correctness */
void checkresult(array c, int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (c[i][j] != (double)n) {
printf("Error: bad number (%f) in result matrix (%d,%d)\n",
c[i][j], i, j);
fflush(stdout);
exit(0);
}
}
/* Run f and return clocks per inner loop iteration */
double run(test_funct f, int n)
{
double cpi;
cpi = fcyc(f, n, CLEARCACHE) / (n*n*n);
checkresult(gc, n);
return(cpi);
}
/* reset result array to zero */
void reset(array c, int n)
{
int i,j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
c[i][j] = 0.0;
}
}
}
/* initialize input arrays to 1 */
void init(array a, array b, int n)
{
int i,j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
a[i][j] = 1.0;
b[i][j] = 1.0;
}
}
}
/* print an array (debug) */
void printarray(array a, int n)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%5.1f ", a[i][j]);
}
printf("\n");
}
}
/***********************************************
* Six different versions of matrix multiply
***********************************************/
void ijk(array A, array B, array C, int n)
{
int i, j, k;
double sum;
/* $begin mm-ijk */
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) {
sum = 0.0;
for (k = 0; k < n; k++)
sum += A[i][k]*B[k][j];
C[i][j] += sum;
}
/* $end mm-ijk */
}
void jik(array A, array B, array C, int n)
{
int i, j, k;
double sum;
/* $begin mm-jik */
for (j = 0; j < n; j++)
for (i = 0; i < n; i++) {
sum = 0.0;
for (k = 0; k < n; k++)
sum += A[i][k]*B[k][j];
C[i][j] += sum;
}
/* $end mm-jik */
}
void ikj(array A, array B, array C, int n)
{
int i, j, k;
double r;
/* $begin mm-ikj */
for (i = 0; i < n; i++)
for (k = 0; k < n; k++) {
r = A[i][k];
for (j = 0; j < n; j++)
C[i][j] += r*B[k][j];
}
/* $end mm-ikj */
}
void kij(array A, array B, array C, int n)
{
int i, j, k;
double r;
/* $begin mm-kij */
for (k = 0; k < n; k++)
for (i = 0; i < n; i++) {
r = A[i][k];
for (j = 0; j < n; j++)
C[i][j] += r*B[k][j];
}
/* $end mm-kij */
}
void kji(array A, array B, array C, int n)
{
int i, j, k;
double r;
/* $begin mm-kji */
for (k = 0; k < n; k++)
for (j = 0; j < n; j++) {
r = B[k][j];
for (i = 0; i < n; i++)
C[i][j] += A[i][k]*r;
}
/* $end mm-kji */
}
void jki(array A, array B, array C, int n)
{
int i, j, k;
double r;
/* $begin mm-jki */
for (j = 0; j < n; j++)
for (k = 0; k < n; k++) {
r = B[k][j];
for (i = 0; i < n; i++)
C[i][j] += A[i][k]*r;
}
/* $end mm-jki */
}
/*
* Run the six versions of matrix multiply and display performance
* as clock cycles per inner loop iteration.
*/
int main()
{
int n;
init(ga, gb, MAXN);
printf("matmult cycles/loop iteration\n");
printf("%3s%6s%6s%6s%6s%6s%6s\n", "n",
"ijk", "jik", "jki", "kji", "kij", "ikj");
fflush(stdout);
for (n = MINN; n <= MAXN; n += INCN) {
printf("%3d ", n);
printf("%5.2f ", run(ijk, n));
printf("%5.2f ", run(jik, n));
printf("%5.2f ", run(jki, n));
printf("%5.2f ", run(kji, n));
printf("%5.2f ", run(kij, n));
printf("%5.2f ", run(ikj, n));
printf("\n");
fflush(stdout);
}
exit(0);
}
================================================
FILE: code/mem/mountain/mountain.c
================================================
/* mountain.c - Generate the memory mountain. */
/* $begin mountainmain */
#include <stdlib.h>
#include <stdio.h>
#include "fcyc2.h" /* measurement routines */
#include "clock.h" /* routines to access the cycle counter */
#define MINBYTES (1 << 11) /* Working set size ranges from 2 KB */
#define MAXBYTES (1 << 25) /* ... up to 64 MB */
#define MAXSTRIDE 64 /* Strides range from 1 to 64 elems */
#define MAXELEMS MAXBYTES/sizeof(double)
/* $begin mountainfuns */
double data[MAXELEMS]; /* The global array we'll be traversing */
/* $end mountainfuns */
/* $end mountainmain */
void init_data(double *data, int n);
void test(int elems, int stride);
double run(int size, int stride, double Mhz);
/* $begin mountainmain */
int main()
{
int size; /* Working set size (in bytes) */
int stride; /* Stride (in array elements) */
double Mhz; /* Clock frequency */
init_data(data, MAXELEMS); /* Initialize each element in data */
Mhz = mhz(0); /* Estimate the clock frequency */
/* $end mountainmain */
/* Not shown in the text */
printf("Clock frequency is approx. %.1f MHz\n", Mhz);
printf("Memory mountain (MB/sec)\n");
printf("\t");
for (stride = 1; stride <= MAXSTRIDE; stride++)
printf("s%d\t", stride);
printf("\n");
/* $begin mountainmain */
for (size = MAXBYTES; size >= MINBYTES; size >>= 1) {
/* $end mountainmain */
/* Not shown in the text */
if (size > (1 << 20))
printf("%dm\t", size / (1 << 20));
else
printf("%dk\t", size / 1024);
/* $begin mountainmain */
for (stride = 1; stride <= MAXSTRIDE; stride++) {
printf("%.1f\t", run(size, stride, Mhz));
}
printf("\n");
}
exit(0);
}
/* $end mountainmain */
/* init_data - initializes the array */
void init_data(double *data, int n)
{
int i;
for (i = 0; i < n; i++)
data[i] = i;
}
/* $begin mountainfuns */
/*
* test - Iterate over first "elems" elements of array "data"
* with stride of "stride".
*/
void test(int elems, int stride) /* The test function */
{
int i;
double result = 0.0;
volatile double sink;
for (i = 0; i < elems; i += stride) {
result += data[i];
}
sink = result; /* So compiler doesn't optimize away the loop */
}
/*
* run - Run test(elems, stride) and return read throughput (MB/s).
* "size" is in bytes, "stride" is in array elements, and
* Mhz is CPU clock frequency in Mhz.
*/
double run(int size, int stride, double Mhz)
{
double cycles;
int elems = size / sizeof(double);
test(elems, stride); /* warm up the cache */ //line:mem:warmup
cycles = fcyc2(test, elems, stride, 0); /* call test(elems,stride) */ //line:mem:fcyc
return (size / stride) / (cycles / Mhz); /* convert cycles to MB/s */ //line:mem:bwcompute
}
/* $end mountainfuns */
================================================
FILE: code/netp/echo.c
================================================
/*
* echo - read and echo text lines until client closes connection
*/
/* $begin echo */
#include "csapp.h"
void echo(int connfd)
{
size_t n;
char buf[MAXLINE];
rio_t rio;
Rio_readinitb(&rio, connfd);
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { //line:netp:echo:eof
printf("server received %d bytes\n", n);
Rio_writen(connfd, buf, n);
}
}
/* $end echo */
================================================
FILE: code/netp/echoclient.c
================================================
/*
* echoclient.c - An echo client
*/
/* $begin echoclientmain */
#include "csapp.h"
int main(int argc, char **argv)
{
int clientfd, port;
char *host, buf[MAXLINE];
rio_t rio;
if (argc != 3) {
fprintf(stderr, "usage: %s <host> <port>\n", argv[0]);
exit(0);
}
host = argv[1];
port = atoi(argv[2]);
clientfd = Open_clientfd(host, port);
Rio_readinitb(&rio, clientfd);
while (Fgets(buf, MAXLINE, stdin) != NULL) {
Rio_writen(clientfd, buf, strlen(buf));
Rio_readlineb(&rio, buf, MAXLINE);
Fputs(buf, stdout);
}
Close(clientfd); //line:netp:echoclient:close
exit(0);
}
/* $end echoclientmain */
================================================
FILE: code/netp/echoserveri.c
================================================
/*
* echoserveri.c - An iterative echo server
*/
/* $begin echoserverimain */
#include "csapp.h"
void echo(int connfd);
int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen;
struct sockaddr_in clientaddr;
struct hostent *hp;
char *haddrp;
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
listenfd = Open_listenfd(port);
while (1) {
clientlen = sizeof(clientaddr);
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
/* determine the domain name and IP address of the client */
hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
haddrp = inet_ntoa(clientaddr.sin_addr);
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
echo(connfd);
Close(connfd);
}
exit(0);
}
/* $end echoserverimain */
================================================
FILE: code/netp/hostinfo.c
================================================
/* $begin hostinfo */
#include "csapp.h"
int main(int argc, char **argv)
{
char **pp;
struct in_addr addr;
struct hostent *hostp;
if (argc != 2) {
fprintf(stderr, "usage: %s <domain name or dotted-decimal>\n",
argv[0]);
exit(0);
}
if (inet_aton(argv[1], &addr) != 0)
hostp = Gethostbyaddr((const char *)&addr, sizeof(addr), AF_INET);
else
hostp = Gethostbyname(argv[1]);
printf("official hostname: %s\n", hostp->h_name);
for (pp = hostp->h_aliases; *pp != NULL; pp++)
printf("alias: %s\n", *pp);
for (pp = hostp->h_addr_list; *pp != NULL; pp++) {
addr.s_addr = ((struct in_addr *)*pp)->s_addr;
printf("address: %s\n", inet_ntoa(addr));
}
exit(0);
}
/* $end hostinfo */
================================================
FILE: code/netp/tiny/cgi-bin/adder.c
================================================
/*
* adder.c - a minimal CGI program that adds two numbers together
*/
/* $begin adder */
#include "csapp.h"
int main(void) {
char *buf, *p;
char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
int n1=0, n2=0;
/* Extract the two arguments */
if ((buf = getenv("QUERY_STRING")) != NULL) {
p = strchr(buf, '&');
*p = '\0';
strcpy(arg1, buf);
strcpy(arg2, p+1);
n1 = atoi(arg1);
n2 = atoi(arg2);
}
/* Make the response body */
sprintf(content, "Welcome to add.com: ");
sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
content, n1, n2, n1 + n2);
sprintf(content, "%sThanks for visiting!\r\n", content);
/* Generate the HTTP response */
printf("Content-length: %d\r\n", (int)strlen(content));
printf("Content-type: text/html\r\n\r\n");
printf("%s", content);
fflush(stdout);
exit(0);
}
/* $end adder */
================================================
FILE: code/netp/tiny/tiny.c
================================================
/* $begin tinymain */
/*
* tiny.c - A simple, iterative HTTP/1.0 Web server that uses the
* GET method to serve static and dynamic content.
*/
#include "csapp.h"
void doit(int fd);
void read_requesthdrs(rio_t *rp);
int parse_uri(char *uri, char *filename, char *cgiargs);
void serve_static(int fd, char *filename, int filesize);
void get_filetype(char *filename, char *filetype);
void serve_dynamic(int fd, char *filename, char *cgiargs);
void clienterror(int fd, char *cause, char *errnum,
char *shortmsg, char *longmsg);
int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen;
struct sockaddr_in clientaddr;
/* Check command line args */
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
port = atoi(argv[1]);
listenfd = Open_listenfd(port);
while (1) {
clientlen = sizeof(clientaddr);
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); //line:netp:tiny:accept
doit(connfd); //line:netp:tiny:doit
Close(connfd); //line:netp:tiny:close
}
}
/* $end tinymain */
/*
* doit - handle one HTTP request/response transaction
*/
/* $begin doit */
void doit(int fd)
{
int is_static;
struct stat sbuf;
char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
char filename[MAXLINE], cgiargs[MAXLINE];
rio_t rio;
/* Read request line and headers */
Rio_readinitb(&rio, fd);
Rio_readlineb(&rio, buf, MAXLINE); //line:netp:doit:readrequest
sscanf(buf, "%s %s %s", method, uri, version); //line:netp:doit:parserequest
if (strcasecmp(method, "GET")) { //line:netp:doit:beginrequesterr
clienterror(fd, method, "501", "Not Implemented",
"Tiny does not implement this method");
return;
} //line:netp:doit:endrequesterr
read_requesthdrs(&rio); //line:netp:doit:readrequesthdrs
/* Parse URI from GET request */
is_static = parse_uri(uri, filename, cgiargs); //line:netp:doit:staticcheck
if (stat(filename, &sbuf) < 0) { //line:netp:doit:beginnotfound
clienterror(fd, filename, "404", "Not found",
"Tiny couldn't find this file");
return;
} //line:netp:doit:endnotfound
if (is_static) { /* Serve static content */
if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { //line:netp:doit:readable
clienterror(fd, filename, "403", "Forbidden",
"Tiny couldn't read the file");
return;
}
serve_static(fd, filename, sbuf.st_size); //line:netp:doit:servestatic
}
else { /* Serve dynamic content */
if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { //line:netp:doit:executable
clienterror(fd, filename, "403", "Forbidden",
"Tiny couldn't run the CGI program");
return;
}
serve_dynamic(fd, filename, cgiargs); //line:netp:doit:servedynamic
}
}
/* $end doit */
/*
* read_requesthdrs - read and parse HTTP request headers
*/
/* $begin read_requesthdrs */
void read_requesthdrs(rio_t *rp)
{
char buf[MAXLINE];
Rio_readlineb(rp, buf, MAXLINE);
while(strcmp(buf, "\r\n")) { //line:netp:readhdrs:checkterm
Rio_readlineb(rp, buf, MAXLINE);
printf("%s", buf);
}
return;
}
/* $end read_requesthdrs */
/*
* parse_uri - parse URI into filename and CGI args
* return 0 if dynamic content, 1 if static
*/
/* $begin parse_uri */
int parse_uri(char *uri, char *filename, char *cgiargs)
{
char *ptr;
if (!strstr(uri, "cgi-bin")) { /* Static content */ //line:netp:parseuri:isstatic
strcpy(cgiargs, ""); //line:netp:parseuri:clearcgi
strcpy(filename, "."); //line:netp:parseuri:beginconvert1
strcat(filename, uri); //line:netp:parseuri:endconvert1
if (uri[strlen(uri)-1] == '/') //line:netp:parseuri:slashcheck
strcat(filename, "home.html"); //line:netp:parseuri:appenddefault
return 1;
}
else { /* Dynamic content */ //line:netp:parseuri:isdynamic
ptr = index(uri, '?'); //line:netp:parseuri:beginextract
if (ptr) {
strcpy(cgiargs, ptr+1);
*ptr = '\0';
}
else
strcpy(cgiargs, ""); //line:netp:parseuri:endextract
strcpy(filename, "."); //line:netp:parseuri:beginconvert2
strcat(filename, uri); //line:netp:parseuri:endconvert2
return 0;
}
}
/* $end parse_uri */
/*
* serve_static - copy a file back to the client
*/
/* $begin serve_static */
void serve_static(int fd, char *filename, int filesize)
{
int srcfd;
char *srcp, filetype[MAXLINE], buf[MAXBUF];
/* Send response headers to client */
get_filetype(filename, filetype); //line:netp:servestatic:getfiletype
sprintf(buf, "HTTP/1.0 200 OK\r\n"); //line:netp:servestatic:beginserve
sprintf(buf, "%sServer: Tiny Web Server\r\n", buf);
sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
Rio_writen(fd, buf, strlen(buf)); //line:netp:servestatic:endserve
/* Send response body to client */
srcfd = Open(filename, O_RDONLY, 0); //line:netp:servestatic:open
srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);//line:netp:servestatic:mmap
Close(srcfd); //line:netp:servestatic:close
Rio_writen(fd, srcp, filesize); //line:netp:servestatic:write
Munmap(srcp, filesize); //line:netp:servestatic:munmap
}
/*
* get_filetype - derive file type from file name
*/
void get_filetype(char *filename, char *filetype)
{
if (strstr(filename, ".html"))
strcpy(filetype, "text/html");
else if (strstr(filename, ".gif"))
strcpy(filetype, "image/gif");
else if (strstr(filename, ".jpg"))
strcpy(filetype, "image/jpeg");
else
strcpy(filetype, "text/plain");
}
/* $end serve_static */
/*
* serve_dynamic - run a CGI program on behalf of the client
*/
/* $begin serve_dynamic */
void serve_dynamic(int fd, char *filename, char *cgiargs)
{
char buf[MAXLINE], *emptylist[] = { NULL };
/* Return first part of HTTP response */
sprintf(buf, "HTTP/1.0 200 OK\r\n");
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Server: Tiny Web Server\r\n");
Rio_writen(fd, buf, strlen(buf));
if (Fork() == 0) { /* child */ //line:netp:servedynamic:fork
/* Real server would set all CGI vars here */
setenv("QUERY_STRING", cgiargs, 1); //line:netp:servedynamic:setenv
Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */ //line:netp:servedynamic:dup2
Execve(filename, emptylist, environ); /* Run CGI program */ //line:netp:servedynamic:execve
}
Wait(NULL); /* Parent waits for and reaps child */ //line:netp:servedynamic:wait
}
/* $end serve_dynamic */
/*
* clienterror - returns an error message to the client
*/
/* $begin clienterror */
void clienterror(int fd, char *cause, char *errnum,
char *shortmsg, char *longmsg)
{
char buf[MAXLINE], body[MAXBUF];
/* Build the HTTP response body */
sprintf(body, "<html><title>Tiny Error</title>");
sprintf(body, "%s<body bgcolor=""ffffff"">\r\n", body);
sprintf(body, "%s%s: %s\r\n", body, errnum, shortmsg);
sprintf(body, "%s<p>%s: %s\r\n", body, longmsg, cause);
sprintf(body, "%s<hr><em>The Tiny Web server</em>\r\n", body);
/* Print the HTTP response */
sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-type: text/html\r\n");
Rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-length: %d\r\n\r\n", (int)strlen(body));
Rio_writen(fd, buf, strlen(buf));
Rio_writen(fd, body, strlen(body));
}
/* $end clienterror */
================================================
FILE: code/src/csapp.c
================================================
/* $begin csapp.c */
#include "csapp.h"
/**************************
* Error-handling functions
**************************/
/* $begin errorfuns */
/* $begin unixerror */
void unix_error(char *msg) /* unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
/* $end unixerror */
void posix_error(int code, char *msg) /* posix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(code));
exit(0);
}
void dns_error(char *msg) /* dns-style error */
{
fprintf(stderr, "%s: DNS error %d\n", msg, h_errno);
exit(0);
}
void app_error(char *msg) /* application error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
/* $end errorfuns */
/*********************************************
* Wrappers for Unix process control functions
********************************************/
/* $begin forkwrapper */
pid_t Fork(void)
{
pid_t pid;
if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}
/* $end forkwrapper */
void Execve(const char *filename, char *const argv[], char *const envp[])
{
if (execve(filename, argv, envp) < 0)
unix_error("Execve error");
}
/* $begin wait */
pid_t Wait(int *status)
{
pid_t pid;
if ((pid = wait(status)) < 0)
unix_error("Wait error");
return pid;
}
/* $end wait */
pid_t Waitpid(pid_t pid, int *iptr, int options)
{
pid_t retpid;
if ((retpid = waitpid(pid, iptr, options)) < 0)
unix_error("Waitpid error");
return(retpid);
}
/* $begin kill */
void Kill(pid_t pid, int signum)
{
int rc;
if ((rc = kill(pid, signum)) < 0)
unix_error("Kill error");
}
/* $end kill */
void Pause()
{
(void)pause();
return;
}
unsigned int Sleep(unsigned int secs)
{
unsigned int rc;
if ((rc = sleep(secs)) < 0)
unix_error("Sleep error");
return rc;
}
unsigned int Alarm(unsigned int seconds) {
return alarm(seconds);
}
void Setpgid(pid_t pid, pid_t pgid) {
int rc;
if ((rc = setpgid(pid, pgid)) < 0)
unix_error("Setpgid error");
return;
}
pid_t Getpgrp(void) {
return getpgrp();
}
/************************************
* Wrappers for Unix signal functions
***********************************/
/* $begin sigaction */
handler_t *Signal(int signum, handler_t *handler)
{
struct sigaction action, old_action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask); /* block sigs of type being handled */
action.sa_flags = SA_RESTART; /* restart syscalls if possible */
if (sigaction(signum, &action, &old_action) < 0)
unix_error("Signal error");
return (old_action.sa_handler);
}
/* $end sigaction */
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
if (sigprocmask(how, set, oldset) < 0)
unix_error("Sigprocmask error");
return;
}
void Sigemptyset(sigset_t *set)
{
if (sigemptyset(set) < 0)
unix_error("Sigemptyset error");
return;
}
void Sigfillset(sigset_t *set)
{
if (sigfillset(set) < 0)
unix_error("Sigfillset error");
return;
}
void Sigaddset(sigset_t *set, int signum)
{
if (sigaddset(set, signum) < 0)
unix_error("Sigaddset error");
return;
}
void Sigdelset(sigset_t *set, int signum)
{
if (sigdelset(set, signum) < 0)
unix_error("Sigdelset error");
return;
}
int Sigismember(const sigset_t *set, int signum)
{
int rc;
if ((rc = sigismember(set, signum)) < 0)
unix_error("Sigismember error");
return rc;
}
/********************************
* Wrappers for Unix I/O routines
********************************/
int Open(const char *pathname, int flags, mode_t mode)
{
int rc;
if ((rc = open(pathname, flags, mode)) < 0)
unix_error("Open error");
return rc;
}
ssize_t Read(int fd, void *buf, size_t count)
{
ssize_t rc;
if ((rc = read(fd, buf, count)) < 0)
unix_error("Read error");
return rc;
}
ssize_t Write(int fd, const void *buf, size_t count)
{
ssize_t rc;
if ((rc = write(fd, buf, count)) < 0)
unix_error("Write error");
return rc;
}
off_t Lseek(int fildes, off_t offset, int whence)
{
off_t rc;
if ((rc = lseek(fildes, offset, whence)) < 0)
unix_error("Lseek error");
return rc;
}
void Close(int fd)
{
int rc;
if ((rc = close(fd)) < 0)
unix_error("Close error");
}
int Select(int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
int rc;
if ((rc = select(n, readfds, writefds, exceptfds, timeout)) < 0)
unix_error("Select error");
return rc;
}
int Dup2(int fd1, int fd2)
{
int rc;
if ((rc = dup2(fd1, fd2)) < 0)
unix_error("Dup2 error");
return rc;
}
void Stat(const char *filename, struct stat *buf)
{
if (stat(filename, buf) < 0)
unix_error("Stat error");
}
void Fstat(int fd, struct stat *buf)
{
if (fstat(fd, buf) < 0)
unix_error("Fstat error");
}
/***************************************
* Wrappers for memory mapping functions
***************************************/
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
void *ptr;
if ((ptr = mmap(addr, len, prot, flags, fd, offset)) == ((void *) -1))
unix_error("mmap error");
return(ptr);
}
void Munmap(void *start, size_t length)
{
if (munmap(start, length) < 0)
unix_error("munmap error");
}
/***************************************************
* Wrappers for dynamic storage allocation functions
***************************************************/
void *Malloc(size_t size)
{
void *p;
if ((p = malloc(size)) == NULL)
unix_error("Malloc error");
return p;
}
void *Realloc(void *ptr, size_t size)
{
void *p;
if ((p = realloc(ptr, size)) == NULL)
unix_error("Realloc error");
return p;
}
void *Calloc(size_t nmemb, size_t size)
{
void *p;
if ((p = calloc(nmemb, size)) == NULL)
unix_error("Calloc error");
return p;
}
void Free(void *ptr)
{
free(ptr);
}
/******************************************
* Wrappers for the Standard I/O functions.
******************************************/
void Fclose(FILE *fp)
{
if (fclose(fp) != 0)
unix_error("Fclose error");
}
FILE *Fdopen(int fd, const char *type)
{
FILE *fp;
if ((fp = fdopen(fd, type)) == NULL)
unix_error("Fdopen error");
return fp;
}
char *Fgets(char *ptr, int n, FILE *stream)
{
char *rptr;
if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream))
app_error("Fgets error");
return rptr;
}
FILE *Fopen(const char *filename, const char *mode)
{
FILE *fp;
if ((fp = fopen(filename, mode)) == NULL)
unix_error("Fopen error");
return fp;
}
void Fputs(const char *ptr, FILE *stream)
{
if (fputs(ptr, stream) == EOF)
unix_error("Fputs error");
}
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t n;
if (((n = fread(ptr, size, nmemb, stream)) < nmemb) && ferror(stream))
unix_error("Fread error");
return n;
}
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (fwrite(ptr, size, nmemb, stream) < nmemb)
unix_error("Fwrite error");
}
/****************************
* Sockets interface wrappers
****************************/
int Socket(int domain, int type, int protocol)
{
int rc;
if ((rc = socket(domain, type, protocol)) < 0)
unix_error("Socket error");
return rc;
}
void Setsockopt(int s, int level, int optname, const void *optval, int optlen)
{
int rc;
if ((rc = setsockopt(s, level, optname, optval, optlen)) < 0)
unix_error("Setsockopt error");
}
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen)
{
int rc;
if ((rc = bind(sockfd, my_addr, addrlen)) < 0)
unix_error("Bind error");
}
void Listen(int s, int backlog)
{
int rc;
if ((rc = listen(s, backlog)) < 0)
unix_error("Listen error");
}
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
int rc;
if ((rc = accept(s, addr, addrlen)) < 0)
unix_error("Accept error");
return rc;
}
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
{
int rc;
if ((rc = connect(sockfd, serv_addr, addrlen)) < 0)
unix_error("Connect error");
}
/************************
* DNS interface wrappers
***********************/
/* $begin gethostbyname */
struct hostent *Gethostbyname(const char *name)
{
struct hostent *p;
if ((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;
}
/* $end gethostbyname */
struct hostent *Gethostbyaddr(const char *addr, int len, int type)
{
struct hostent *p;
if ((p = gethostbyaddr(addr, len, type)) == NULL)
dns_error("Gethostbyaddr error");
return p;
}
/************************************************
* Wrappers for Pthreads thread control functions
************************************************/
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void * (*routine)(void *), void *argp)
{
int rc;
if ((rc = pthread_create(tidp, attrp, routine, argp)) != 0)
posix_error(rc, "Pthread_create error");
}
void Pthread_cancel(pthread_t tid) {
int rc;
if ((rc = pthread_cancel(tid)) != 0)
posix_error(rc, "Pthread_cancel error");
}
void Pthread_join(pthread_t tid, void **thread_return) {
int rc;
if ((rc = pthread_join(tid, thread_return)) != 0)
posix_error(rc, "Pthread_join error");
}
/* $begin detach */
void Pthread_detach(pthread_t tid) {
int rc;
if ((rc = pthread_detach(tid)) != 0)
posix_error(rc, "Pthread_detach error");
}
/* $end detach */
void Pthread_exit(void *retval) {
pthread_exit(retval);
}
pthread_t Pthread_self(void) {
return pthread_self();
}
void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
pthread_once(once_control, init_function);
}
/*******************************
* Wrappers for Posix semaphores
*******************************/
void Sem_init(sem_t *sem, int pshared, unsigned int value)
{
if (sem_init(sem, pshared, value) < 0)
unix_error("Sem_init error");
}
void P(sem_t *sem)
{
if (sem_wait(sem) < 0)
unix_error("P error");
}
void V(sem_t *sem)
{
if (sem_post(sem) < 0)
unix_error("V error");
}
/*********************************************************************
* The Rio package - robust I/O functions
**********************************************************************/
/*
* rio_readn - robustly read n bytes (unbuffered)
*/
/* $begin rio_readn */
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = read(fd, bufp, nleft)) < 0) {
if (errno == EINTR) /* interrupted by sig handler return */
nread = 0; /* and call read() again */
else
return -1; /* errno set by read() */
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* return >= 0 */
}
/* $end rio_readn */
/*
* rio_writen - robustly write n bytes (unbuffered)
*/
/* $begin rio_writen */
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nwritten;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
if (errno == EINTR) /* interrupted by sig handler return */
nwritten = 0; /* and call write() again */
else
return -1; /* errno set by write() */
}
nleft -= nwritten;
bufp += nwritten;
}
return n;
}
/* $end rio_writen */
/*
* rio_read - This is a wrapper for the Unix read() function that
* transfers min(n, rio_cnt) bytes from an internal buffer to a user
* buffer, where n is the number of bytes requested by the user and
* rio_cnt is the number of unread bytes in the internal buffer. On
* entry, rio_read() refills the internal buffer via a call to
* read() if the internal buffer is empty.
*/
/* $begin rio_read */
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
int cnt;
while (rp->rio_cnt <= 0) { /* refill if buf is empty */
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
sizeof(rp->rio_buf));
if (rp->rio_cnt < 0) {
if (errno != EINTR) /* interrupted by sig handler return */
return -1;
}
else if (rp->rio_cnt == 0) /* EOF */
return 0;
else
rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */
}
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
cnt = n;
if (rp->rio_cnt < n)
cnt = rp->rio_cnt;
memcpy(usrbuf, rp->rio_bufptr, cnt);
rp->rio_bufptr += cnt;
rp->rio_cnt -= cnt;
return cnt;
}
/* $end rio_read */
/*
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer
*/
/* $begin rio_readinitb */
void rio_readinitb(rio_t *rp, int fd)
{
rp->rio_fd = fd;
rp->rio_cnt = 0;
rp->rio_bufptr = rp->rio_buf;
}
/* $end rio_readinitb */
/*
* rio_readnb - Robustly read n bytes (buffered)
*/
/* $begin rio_readnb */
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = rio_read(rp, bufp, nleft)) < 0) {
if (errno == EINTR) /* interrupted by sig handler return */
nread = 0; /* call read() again */
else
return -1; /* errno set by read() */
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* return >= 0 */
}
/* $end rio_readnb */
/*
* rio_readlineb - robustly read a text line (buffered)
*/
/* $begin rio_readlineb */
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
int n, rc;
char c, *bufp = usrbuf;
for (n = 1; n < maxlen; n++) {
if ((rc = rio_read(rp, &c, 1)) == 1) {
*bufp++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
if (n == 1)
return 0; /* EOF, no data read */
else
break; /* EOF, some data was read */
} else
return -1; /* error */
}
*bufp = 0;
return n;
}
/* $end rio_readlineb */
/**********************************
* Wrappers for robust I/O routines
**********************************/
ssize_t Rio_readn(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ((n = rio_readn(fd, ptr, nbytes)) < 0)
unix_error("Rio_readn error");
return n;
}
void Rio_writen(int fd, void *usrbuf, size_t n)
{
if (rio_writen(fd, usrbuf, n) != n)
unix_error("Rio_writen error");
}
void Rio_readinitb(rio_t *rp, int fd)
{
rio_readinitb(rp, fd);
}
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
ssize_t rc;
if ((rc = rio_readnb(rp, usrbuf, n)) < 0)
unix_error("Rio_readnb error");
return rc;
}
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
ssize_t rc;
if ((rc = rio_readlineb(rp, usrbuf, maxlen)) < 0)
unix_error("Rio_readlineb error");
return rc;
}
/********************************
* Client/server helper functions
********************************/
/*
* open_clientfd - open connection to server at <hostname, port>
* and return a socket descriptor ready for reading and writing.
* Returns -1 and sets errno on Unix error.
* Returns -2 and sets h_errno on DNS (gethostbyname) error.
*/
/* $begin open_clientfd */
int open_clientfd(char *hostname, int port)
{
int clientfd;
struct hostent *hp;
struct sockaddr_in serveraddr;
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1; /* check errno for cause of error */
/* Fill in the server's IP address and port */
if ((hp = gethostbyname(hostname)) == NULL)
return -2; /* check h_errno for cause of error */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr_list[0],
(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
serveraddr.sin_port = htons(port);
/* Establish a connection with the server */
if (connect(clientfd, (SA *) &serveraddr, sizeof(serveraddr)) < 0)
return -1;
return clientfd;
}
/* $end open_clientfd */
/*
* open_listenfd - open and return a listening socket on port
* Returns -1 and sets errno on Unix error.
*/
/* $begin open_listenfd */
int open_listenfd(int port)
{
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int)) < 0)
return -1;
/* Listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0)
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0)
return -1;
return listenfd;
}
/* $end open_listenfd */
/******************************************
* Wrappers for the client/server helper routines
******************************************/
int Open_clientfd(char *hostname, int port)
{
int rc;
if ((rc = open_clientfd(hostname, port)) < 0) {
if (rc == -1)
unix_error("Open_clientfd Unix error");
else
dns_error("Open_clientfd DNS error");
}
return rc;
}
int Open_listenfd(int port)
{
int rc;
if ((rc = open_listenfd(port)) < 0)
unix_error("Open_listenfd error");
return rc;
}
/* $end csapp.c */
================================================
FILE: code/vm/malloc/memlib.c
================================================
/*
* memlib.c - a module that simulates the memory system. Needed
* because it allows us to interleave calls from the student's malloc
* package with the system's malloc package in libc.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include "csapp.h"
#include "memlib.h"
#include "config.h"
/* $begin memlib */
/* Private global variables */
static char *mem_heap; /* Points to first byte of heap */
static char *mem_brk; /* Points to last byte of heap plus 1 */
static char *mem_max_addr; /* Max legal heap addr plus 1*/
/*
* mem_init - Initialize the memory system model
*/
void mem_init(void)
{
mem_heap = (char *)Malloc(MAX_HEAP);
mem_brk = (char *)mem_heap;
mem_max_addr = (char *)(mem_heap + MAX_HEAP);
}
/*
* mem_sbrk - Simple model of the sbrk function. Extends the heap
* by incr bytes and returns the start address of the new area. In
* this model, the heap cannot be shrunk.
*/
void *mem_sbrk(int incr)
{
char *old_brk = mem_brk;
if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) {
errno = ENOMEM;
fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory...\n");
return (void *)-1;
}
mem_brk += incr;
return (void *)old_brk;
}
/* $end memlib */
/*
* mem_deinit - free the storage used by the memory system model
*/
void mem_deinit(void)
{
}
/*
* mem_reset_brk - reset the simulated brk pointer to make an empty heap
*/
void mem_reset_brk()
{
mem_brk = (char *)mem_heap;
}
/*
* mem_heap_lo - return address of the first heap byte
*/
void *mem_heap_lo()
{
return (void *)mem_heap;
}
/*
* mem_heap_hi - return address of last heap byte
*/
void *mem_heap_hi()
{
return (void *)(mem_brk - 1);
}
/*
* mem_heapsize() - returns the heap size in bytes
*/
size_t mem_heapsize()
{
return (size_t)((void *)mem_brk - (void *)mem_heap);
}
/*
* mem_pagesize() - returns the page size of the system
*/
size_t mem_pagesize()
{
return (size_t)getpagesize();
}
================================================
FILE: code/vm/malloc/mm.c
================================================
/*
* Simple, 32-bit and 64-bit clean allocator based on implicit free
* lists, first fit placement, and boundary tag coalescing, as described
* in the CS:APP2e text. Blocks must be aligned to doubleword (8 byte)
* boundaries. Minimum block size is 16 bytes.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mm.h"
#include "memlib.h"
/*
* If NEXT_FIT defined use next fit search, else use first fit search
*/
#define NEXT_FITx
/* $begin mallocmacros */
/* Basic constants and macros */
#define WSIZE 4 /* Word and header/footer size (bytes) */ //line:vm:mm:beginconst
#define DSIZE 8 /* Doubleword size (bytes) */
#define CHUNKSIZE (1<<12) /* Extend heap by this amount (bytes) */ //line:vm:mm:endconst
#define MAX(x, y) ((x) > (y)? (x) : (y))
/* Pack a size and allocated bit into a word */
#define PACK(size, alloc) ((size) | (alloc)) //line:vm:mm:pack
/* Read and write a word at address p */
#define GET(p) (*(unsigned int *)(p)) //line:vm:mm:get
#define PUT(p, val) (*(unsigned int *)(p) = (val)) //line:vm:mm:put
/* Read the size and allocated fields from address p */
#define GET_SIZE(p) (GET(p) & ~0x7) //line:vm:mm:getsize
#define GET_ALLOC(p) (GET(p) & 0x1) //line:vm:mm:getalloc
/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp) ((char *)(bp) - WSIZE) //line:vm:mm:hdrp
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) //line:vm:mm:ftrp
/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) //line:vm:mm:nextblkp
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) //line:vm:mm:prevblkp
/* $end mallocmacros */
/* Global variables */
static char *heap_listp = 0; /* Pointer to first block */
#ifdef NEXT_FIT
static char *rover; /* Next fit rover */
#endif
/* Function prototypes for internal helper routines */
static void *extend_heap(size_t words);
static void place(void *bp, size_t asize);
static void *find_fit(size_t asize);
static void *coalesce(void *bp);
static void printblock(void *bp);
static void checkheap(int verbose);
static void checkblock(void *bp);
/*
* mm_init - Initialize the memory manager
*/
/* $begin mminit */
int mm_init(void)
{
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1) //line:vm:mm:begininit
return -1;
PUT(heap_listp, 0); /* Alignment padding */
PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 1)); /* Prologue header */
PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 1)); /* Prologue footer */
PUT(heap_listp + (3*WSIZE), PACK(0, 1)); /* Epilogue header */
heap_listp += (2*WSIZE); //line:vm:mm:endinit
/* $end mminit */
#ifdef NEXT_FIT
rover = heap_listp;
#endif
/* $begin mminit */
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
return -1;
return 0;
}
/* $end mminit */
/*
* mm_malloc - Allocate a block with at least size bytes of payload
*/
/* $begin mmmalloc */
void *mm_malloc(size_t size)
{
size_t asize; /* Adjusted block size */
size_t extendsize; /* Amount to extend heap if no fit */
char *bp;
/* $end mmmalloc */
if (heap_listp == 0){
mm_init();
}
/* $begin mmmalloc */
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignment reqs. */
if (size <= DSIZE) //line:vm:mm:sizeadjust1
asize = 2*DSIZE; //line:vm:mm:sizeadjust2
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE); //line:vm:mm:sizeadjust3
/* Search the free list for a fit */
if ((bp = find_fit(asize)) != NULL) { //line:vm:mm:findfitcall
place(bp, asize); //line:vm:mm:findfitplace
return bp;
}
/* No fit found. Get more memory and place the block */
extendsize = MAX(asize,CHUNKSIZE); //line:vm:mm:growheap1
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL; //line:vm:mm:growheap2
place(bp, asize); //line:vm:mm:growheap3
return bp;
}
/* $end mmmalloc */
/*
* mm_free - Free a block
*/
/* $begin mmfree */
void mm_free(void *bp)
{
/* $end mmfree */
if(bp == 0)
return;
/* $begin mmfree */
size_t size = GET_SIZE(HDRP(bp));
/* $end mmfree */
if (heap_listp == 0){
mm_init();
}
/* $begin mmfree */
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
coalesce(bp);
}
/* $end mmfree */
/*
* coalesce - Boundary tag coalescing. Return ptr to coalesced block
*/
/* $begin mmfree */
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc) { /* Case 1 */
return bp;
}
else if (prev_alloc && !next_alloc) { /* Case 2 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size,0));
}
else if (!prev_alloc && next_alloc) { /* Case 3 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
else { /* Case 4 */
size += GET_SIZE(HDRP(PREV_BLKP(bp))) +
GET_SIZE(FTRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
/* $end mmfree */
#ifdef NEXT_FIT
/* Make sure the rover isn't pointing into the free block */
/* that we just coalesced */
if ((rover > (char *)bp) && (rover < NEXT_BLKP(bp)))
rover = bp;
#endif
/* $begin mmfree */
return bp;
}
/* $end mmfree */
/*
* mm_realloc - Naive implementation of realloc
*/
void *mm_realloc(void *ptr, size_t size)
{
size_t oldsize;
void *newptr;
/* If size == 0 then this is just free, and we return NULL. */
if(size == 0) {
mm_free(ptr);
return 0;
}
/* If oldptr is NULL, then this is just malloc. */
if(ptr == NULL) {
return mm_malloc(size);
}
newptr = mm_malloc(size);
/* If realloc() fails the original block is left untouched */
if(!newptr) {
return 0;
}
/* Copy the old data. */
oldsize = GET_SIZE(HDRP(ptr));
if(size < oldsize) oldsize = size;
memcpy(newptr, ptr, oldsize);
/* Free the old block. */
mm_free(ptr);
return newptr;
}
/*
* checkheap - We don't check anything right now.
*/
void mm_checkheap(int verbose)
{
}
/*
* The remaining routines are internal helper routines
*/
/*
* extend_heap - Extend heap with free block and return its block pointer
*/
/* $begin mmextendheap */
static void *extend_heap(size_t words)
{
char *bp;
size_t size;
/* Allocate an even number of words to maintain alignment */
size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; //line:vm:mm:beginextend
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL; //line:vm:mm:endextend
/* Initialize free block header/footer and the epilogue header */
PUT(HDRP(bp), PACK(size, 0)); /* Free block header */ //line:vm:mm:freeblockhdr
PUT(FTRP(bp), PACK(size, 0)); /* Free block footer */ //line:vm:mm:freeblockftr
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* New epilogue header */ //line:vm:mm:newepihdr
/* Coalesce if the previous block was free */
return coalesce(bp); //line:vm:mm:returnblock
}
/* $end mmextendheap */
/*
* place - Place block of asize bytes at start of free block bp
* and split if remainder would be at least minimum block size
*/
/* $begin mmplace */
/* $begin mmplace-proto */
static void place(void *bp, size_t asize)
/* $end mmplace-proto */
{
size_t csize = GET_SIZE(HDRP(bp));
if ((csize - asize) >= (2*DSIZE)) {
PUT(HDRP(bp), PACK(asize, 1));
PUT(FTRP(bp), PACK(asize, 1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(csize-asize, 0));
PUT(FTRP(bp), PACK(csize-asize, 0));
}
else {
PUT(HDRP(bp), PACK(csize, 1));
PUT(FTRP(bp), PACK(csize, 1));
}
}
/* $end mmplace */
/*
* find_fit - Find a fit for a block with asize bytes
*/
/* $begin mmfirstfit */
/* $begin mmfirstfit-proto */
static void *find_fit(size_t asize)
/* $end mmfirstfit-proto */
{
/* $end mmfirstfit */
#ifdef NEXT_FIT
/* Next fit search */
char *oldrover = rover;
/* Search from the rover to the end of list */
for ( ; GET_SIZE(HDRP(rover)) > 0; rover = NEXT_BLKP(rover))
if (!GET_ALLOC(HDRP(rover)) && (asize <= GET_SIZE(HDRP(rover))))
return rover;
/* search from start of list to old rover */
for (rover = heap_listp; rover < oldrover; rover = NEXT_BLKP(rover))
if (!GET_ALLOC(HDRP(rover)) && (asize <= GET_SIZE(HDRP(rover))))
return rover;
return NULL; /* no fit found */
#else
/* $begin mmfirstfit */
/* First fit search */
void *bp;
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp)))) {
return bp;
}
}
return NULL; /* No fit */
/* $end mmfirstfit */
#endif
}
static void printblock(void *bp)
{
size_t hsize, halloc, fsize, falloc;
checkheap(0);
hsize = GET_SIZE(HDRP(bp));
halloc = GET_ALLOC(HDRP(bp));
fsize = GET_SIZE(FTRP(bp));
falloc = GET_ALLOC(FTRP(bp));
if (hsize == 0) {
printf("%p: EOL\n", bp);
return;
}
/* printf("%p: header: [%p:%c] footer: [%p:%c]\n", bp,
hsize, (halloc ? 'a' : 'f'),
fsize, (falloc ? 'a' : 'f')); */
}
static void checkblock(void *bp)
{
if ((size_t)bp % 8)
printf("Error: %p is not doubleword aligned\n", bp);
if (GET(HDRP(bp)) != GET(FTRP(bp)))
printf("Error: header does not match footer\n");
}
/*
* checkheap - Minimal check of the heap for consistency
*/
void checkheap(int verbose)
{
char *bp = heap_listp;
if (verbose)
printf("Heap (%p):\n", heap_listp);
if ((GET_SIZE(HDRP(heap_listp)) != DSIZE) || !GET_ALLOC(HDRP(heap_listp)))
printf("Bad prologue header\n");
checkblock(heap_listp);
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (verbose)
printblock(bp);
checkblock(bp);
}
if (verbose)
printblock(bp);
if ((GET_SIZE(HDRP(bp)) != 0) || !(GET_ALLOC(HDRP(bp))))
printf("Bad epilogue header\n");
}
================================================
FILE: code/vm/memlib.h
================================================
void *mem_init(int size);
void *mem_sbrk(int incr);
================================================
FILE: code/vm/mm.h
================================================
/* $begin mallocinterface */
int mm_init(void);
void *mm_malloc(size_t size);
void mm_free(void *bp);
/* $end mallocinterface */
void mm_checkheap(int verbose);
void *mm_realloc(void *ptr, size_t size);
/* Unused. Just to keep us compatible with the 15-213 malloc driver */
typedef struct {
char *team;
char *name1, *email1;
char *name2, *email2;
} team_t;
extern team_t team;
================================================
FILE: common/csapp.c
================================================
/* $begin csapp.c */
#include "csapp.h"
/**************************
* Error-handling functions
**************************/
/* $begin errorfuns */
/* $begin unixerror */
void unix_error(char *msg) /* unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
/* $end unixerror */
void posix_error(int code, char *msg) /* posix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(code));
exit(0);
}
void dns_error(char *msg) /* dns-style error */
{
fprintf(stderr, "%s: DNS error %d\n", msg, h_errno);
exit(0);
}
void app_error(char *msg) /* application error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
/* $end errorfuns */
/*********************************************
* Wrappers for Unix process control functions
********************************************/
/* $begin forkwrapper */
pid_t Fork(void)
{
pid_t pid;
if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}
/* $end forkwrapper */
void Execve(const char *filename, char *const argv[], char *const envp[])
{
if (execve(filename, argv, envp) < 0)
unix_error("Execve error");
}
/* $begin wait */
pid_t Wait(int *status)
{
pid_t pid;
if ((pid = wait(status)) < 0)
unix_error("Wait error");
return pid;
}
/* $end wait */
pid_t Waitpid(pid_t pid, int *iptr, int options)
{
pid_t retpid;
if ((retpid = waitpid(pid, iptr, options)) < 0)
unix_error("Waitpid error");
return(retpid);
}
/* $begin kill */
void Kill(pid_t pid, int signum)
{
int rc;
if ((rc = kill(pid, signum)) < 0)
unix_error("Kill error");
}
/* $end kill */
void Pause()
{
(void)pause();
return;
}
unsigned int Sleep(unsigned int secs)
{
unsigned int rc;
if ((rc = sleep(secs)) < 0)
unix_error("Sleep error");
return rc;
}
unsigned int Alarm(unsigned int seconds) {
return alarm(seconds);
}
void Setpgid(pid_t pid, pid_t pgid) {
int rc;
if ((rc = setpgid(pid, pgid)) < 0)
unix_error("Setpgid error");
return;
}
pid_t Getpgrp(void) {
return getpgrp();
}
/************************************
* Wrappers for Unix signal functions
***********************************/
/* $begin sigaction */
handler_t *Signal(int signum, handler_t *handler)
{
struct sigaction action, old_action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask); /* block sigs of type being handled */
action.sa_flags = SA_RESTART; /* restart syscalls if possible */
if (sigaction(signum, &action, &old_action) < 0)
unix_error("Signal error");
return (old_action.sa_handler);
}
/* $end sigaction */
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
if (sigprocmask(how, set, oldset) < 0)
unix_error("Sigprocmask error");
return;
}
void Sigemptyset(sigset_t *set)
{
if (sigemptyset(set) < 0)
unix_error("Sigemptyset error");
return;
}
void Sigfillset(sigset_t *set)
{
if (sigfillset(set) < 0)
unix_error("Sigfillset error");
return;
}
void Sigaddset(sigset_t *set, int signum)
{
if (sigaddset(set, signum) < 0)
unix_error("Sigaddset error");
return;
}
void Sigdelset(sigset_t *set, int signum)
{
if (sigdelset(set, signum) < 0)
unix_error("Sigdelset error");
return;
}
int Sigismember(const sigset_t *set, int signum)
{
int rc;
if ((rc = sigismember(set, signum)) < 0)
unix_error("Sigismember error");
return rc;
}
/********************************
* Wrappers for Unix I/O routines
********************************/
int Open(const char *pathname, int flags, mode_t mode)
{
int rc;
if ((rc = open(pathname, flags, mode)) < 0)
unix_error("Open error");
return rc;
}
ssize_t Read(int fd, void *buf, size_t count)
{
ssize_t rc;
if ((rc = read(fd, buf, count)) < 0)
unix_error("Read error");
return rc;
}
ssize_t Write(int fd, const void *buf, size_t count)
{
ssize_t rc;
if ((rc = write(fd, buf, count)) < 0)
unix_error("Write error");
return rc;
}
off_t Lseek(int fildes, off_t offset, int whence)
{
off_t rc;
if ((rc = lseek(fildes, offset, whence)) < 0)
unix_error("Lseek error");
return rc;
}
void Close(int fd)
{
int rc;
if ((rc = close(fd)) < 0)
unix_error("Close error");
}
int Select(int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
int rc;
if ((rc = select(n, readfds, writefds, exceptfds, timeout)) < 0)
unix_error("Select error");
return rc;
}
int Dup2(int fd1, int fd2)
{
int rc;
if ((rc = dup2(fd1, fd2)) < 0)
unix_error("Dup2 error");
return rc;
}
void Stat(const char *filename, struct stat *buf)
{
if (stat(filename, buf) < 0)
unix_error("Stat error");
}
void Fstat(int fd, struct stat *buf)
{
if (fstat(fd, buf) < 0)
unix_error("Fstat error");
}
/***************************************
* Wrappers for memory mapping functions
***************************************/
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
void *ptr;
if ((ptr = mmap(addr, len, prot, flags, fd, offset)) == ((void *) -1))
unix_error("mmap error");
return(ptr);
}
void Munmap(void *start, size_t length)
{
if (munmap(start, length) < 0)
unix_error("munmap error");
}
/***************************************************
* Wrappers for dynamic storage allocation functions
***************************************************/
void *Malloc(size_t size)
{
void *p;
if ((p = malloc(size)) == NULL)
unix_error("Malloc error");
return p;
}
void *Realloc(void *ptr, size_t size)
{
void *p;
if ((p = realloc(ptr, size)) == NULL)
unix_error("Realloc error");
return p;
}
void *Calloc(size_t nmemb, size_t size)
{
void *p;
if ((p = calloc(nmemb, size)) == NULL)
unix_error("Calloc error");
return p;
}
void Free(void *ptr)
{
free(ptr);
}
/******************************************
* Wrappers for the Standard I/O functions.
******************************************/
void Fclose(FILE *fp)
{
if (fclose(fp) != 0)
unix_error("Fclose error");
}
FILE *Fdopen(int fd, const char *type)
{
FILE *fp;
if ((fp = fdopen(fd, type)) == NULL)
unix_error("Fdopen error");
return fp;
}
char *Fgets(char *ptr, int n, FILE *stream)
{
char *rptr;
if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream))
app_error("Fgets error");
return rptr;
}
FILE *Fopen(const char *filename, const char *mode)
{
FILE *fp;
if ((fp = fopen(filename, mode)) == NULL)
unix_error("Fopen error");
return fp;
}
void Fputs(const char *ptr, FILE *stream)
{
if (fputs(ptr, stream) == EOF)
unix_error("Fputs error");
}
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t n;
if (((n = fread(ptr, size, nmemb, stream)) < nmemb) && ferror(stream))
unix_error("Fread error");
return n;
}
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (fwrite(ptr, size, nmemb, stream) < nmemb)
unix_error("Fwrite error");
}
/****************************
* Sockets interface wrappers
****************************/
int Socket(int domain, int type, int protocol)
{
int rc;
if ((rc = socket(domain, type, protocol)) < 0)
unix_error("Socket error");
return rc;
}
void Setsockopt(int s, int level, int optname, const void *optval, int optlen)
{
int rc;
if ((rc = setsockopt(s, level, optname, optval, optlen)) < 0)
unix_error("Setsockopt error");
}
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen)
{
int rc;
if ((rc = bind(sockfd, my_addr, addrlen)) < 0)
unix_error("Bind error");
}
void Listen(int s, int backlog)
{
int rc;
if ((rc = listen(s, backlog)) < 0)
unix_error("Listen error");
}
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
int rc;
if ((rc = accept(s, addr, addrlen)) < 0)
unix_error("Accept error");
return rc;
}
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
{
int rc;
if ((rc = connect(sockfd, serv_addr, addrlen)) < 0)
unix_error("Connect error");
}
/************************
* DNS interface wrappers
***********************/
/* $begin gethostbyname */
struct hostent *Gethostbyname(const char *name)
{
struct hostent *p;
if ((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;
}
/* $end gethostbyname */
struct hostent *Gethostbyaddr(const char *addr, int len, int type)
{
struct hostent *p;
if ((p = gethostbyaddr(addr, len, type)) == NULL)
dns_error("Gethostbyaddr error");
return p;
}
/************************************************
* Wrappers for Pthreads thread control functions
************************************************/
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void * (*routine)(void *), void *argp)
{
int rc;
if ((rc = pthread_create(tidp, attrp, routine, argp)) != 0)
posix_error(rc, "Pthread_create error");
}
void Pthread_cancel(pthread_t tid) {
int rc;
if ((rc = pthread_cancel(tid)) != 0)
posix_error(rc, "Pthread_cancel error");
}
void Pthread_join(pthread_t tid, void **thread_return) {
int rc;
if ((rc = pthread_join(tid, thread_return)) != 0)
posix_error(rc, "Pthread_join error");
}
/* $begin detach */
void Pthread_detach(pthread_t tid) {
int rc;
if ((rc = pthread_detach(tid)) != 0)
posix_error(rc, "Pthread_detach error");
}
/* $end detach */
void Pthread_exit(void *retval) {
pthread_exit(retval);
}
pthread_t Pthread_self(void) {
return pthread_self();
}
void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
pthread_once(once_control, init_function);
}
/*******************************
* Wrappers for Posix semaphores
*******************************/
void Sem_init(sem_t *sem, int pshared, unsigned int value)
{
if (sem_init(sem, pshared, value) < 0)
unix_error("Sem_init error");
}
void P(sem_t *sem)
{
if (sem_wait(sem) < 0)
unix_error("P error");
}
void V(sem_t *sem)
{
if (sem_post(sem) < 0)
unix_error("V error");
}
/*********************************************************************
* The Rio package - robust I/O functions
**********************************************************************/
/*
* rio_readn - robustly read n bytes (unbuffered)
*/
/* $begin rio_readn */
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = read(fd, bufp, nleft)) < 0) {
if (errno == EINTR) /* interrupted by sig handler return */
nread = 0; /* and call read() again */
else
return -1; /* errno set by read() */
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* return >= 0 */
}
/* $end rio_readn */
/*
* rio_writen - robustly write n bytes (unbuffered)
*/
/* $begin rio_writen */
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nwritten;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
if (errno == EINTR) /* interrupted by sig handler return */
nwritten = 0; /* and call write() again */
else
return -1; /* errno set by write() */
}
nleft -= nwritten;
bufp += nwritten;
}
return n;
}
/* $end rio_writen */
/*
* rio_read - This is a wrapper for the Unix read() function that
* transfers min(n, rio_cnt) bytes from an internal buffer to a user
* buffer, where n is the number of bytes requested by the user and
* rio_cnt is the number of unread bytes in the internal buffer. On
* entry, rio_read() refills the internal buffer via a call to
* read() if the internal buffer is empty.
*/
/* $begin rio_read */
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
int cnt;
while (rp->rio_cnt <= 0) { /* refill if buf is empty */
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
sizeof(rp->rio_buf));
if (rp->rio_cnt < 0) {
if (errno != EINTR) /* interrupted by sig handler return */
return -1;
}
else if (rp->rio_cnt == 0) /* EOF */
return 0;
else
rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */
}
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
cnt = n;
if (rp->rio_cnt < n)
cnt = rp->rio_cnt;
memcpy(usrbuf, rp->rio_bufptr, cnt);
rp->rio_bufptr += cnt;
rp->rio_cnt -= cnt;
return cnt;
}
/* $end rio_read */
/*
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer
*/
/* $begin rio_readinitb */
void rio_readinitb(rio_t *rp, int fd)
{
rp->rio_fd = fd;
rp->rio_cnt = 0;
rp->rio_bufptr = rp->rio_buf;
}
/* $end rio_readinitb */
/*
* rio_readnb - Robustly read n bytes (buffered)
*/
/* $begin rio_readnb */
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = rio_read(rp, bufp, nleft)) < 0) {
if (errno == EINTR) /* interrupted by sig handler return */
nread = 0; /* call read() again */
else
return -1; /* errno set by read() */
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* return >= 0 */
}
/* $end rio_readnb */
/*
* rio_readlineb - robustly read a text line (buffered)
*/
/* $begin rio_readlineb */
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
int n, rc;
char c, *bufp = usrbuf;
for (n = 1; n < maxlen; n++) {
if ((rc = rio_read(rp, &c, 1)) == 1) {
*bufp++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
if (n == 1)
return 0; /* EOF, no data read */
else
break; /* EOF, some data was read */
} else
return -1; /* error */
}
*bufp = 0;
return n;
}
/* $end rio_readlineb */
/**********************************
* Wrappers for robust I/O routines
**********************************/
ssize_t Rio_readn(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ((n = rio_readn(fd, ptr, nbytes)) < 0)
unix_error("Rio_readn error");
return n;
}
void Rio_writen(int fd, void *usrbuf, size_t n)
{
if (rio_writen(fd, usrbuf, n) != n)
unix_error("Rio_writen error");
}
void Rio_readinitb(rio_t *rp, int fd)
{
rio_readinitb(rp, fd);
}
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
ssize_t rc;
if ((rc = rio_readnb(rp, usrbuf, n)) < 0)
unix_error("Rio_readnb error");
return rc;
}
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
ssize_t rc;
if ((rc = rio_readlineb(rp, usrbuf, maxlen)) < 0)
unix_error("Rio_readlineb error");
return rc;
}
/********************************
* Client/server helper functions
********************************/
/*
* open_clientfd - open connection to server at <hostname, port>
* and return a socket descriptor ready for reading and writing.
* Returns -1 and sets errno on Unix error.
* Returns -2 and sets h_errno on DNS (gethostbyname) error.
*/
/* $begin open_clientfd */
int open_clientfd(char *hostname, int port)
{
int clientfd;
struct hostent *hp;
struct sockaddr_in serveraddr;
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1; /* check errno for cause of error */
/* Fill in the server's IP address and port */
if ((hp = gethostbyname(hostname)) == NULL)
return -2; /* check h_errno for cause of error */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr_list[0],
(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
serveraddr.sin_port = htons(port);
/* Establish a connection with the server */
if (connect(clientfd, (SA *) &serveraddr, sizeof(serveraddr)) < 0)
return -1;
return clientfd;
}
/* $end open_clientfd */
/*
* open_listenfd - open and return a listening socket on port
* Returns -1 and sets errno on Unix error.
*/
/* $begin open_listenfd */
int open_listenfd(int port)
{
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int)) < 0)
return -1;
/* Listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0)
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0)
return -1;
return listenfd;
}
/* $end open_listenfd */
/******************************************
* Wrappers for the client/server helper routines
******************************************/
int Open_clientfd(char *hostname, int port)
{
int rc;
if ((rc = open_clientfd(hostname, port)) < 0) {
if (rc == -1)
unix_error("Open_clientfd Unix error");
else
dns_error("Open_clientfd DNS error");
}
return rc;
}
int Open_listenfd(int port)
{
int rc;
if ((rc = open_listenfd(port)) < 0)
unix_error("Open_listenfd error");
return rc;
}
/* $end csapp.c */
================================================
FILE: common/csapp.h
================================================
/* $begin csapp.h */
#ifndef __CSAPP_H__
#define __CSAPP_H__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* Default file permissions are DEF_MODE & ~DEF_UMASK */
/* $begin createmasks */
#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
#define DEF_UMASK S_IWGRP|S_IWOTH
/* $end createmasks */
/* Simplifies calls to bind(), connect(), and accept() */
/* $begin sockaddrdef */
typedef struct sockaddr SA;
/* $end sockaddrdef */
/* Persistent state for the robust I/O (Rio) package */
/* $begin rio_t */
#define RIO_BUFSIZE 8192
typedef struct {
int rio_fd; /* descriptor for this internal buf */
int rio_cnt; /* unread bytes in internal buf */
char *rio_bufptr; /* next unread byte in internal buf */
char rio_buf[RIO_BUFSIZE]; /* internal buffer */
} rio_t;
/* $end rio_t */
/* External variables */
extern int h_errno; /* defined by BIND for DNS errors */
extern char **environ; /* defined by libc */
/* Misc constants */
#define MAXLINE 8192 /* max text line length */
#define MAXBUF 8192 /* max I/O buffer size */
#define LISTENQ 1024 /* second argument to listen() */
/* Our own error-handling functions */
void unix_error(char *msg);
void posix_error(int code, char *msg);
void dns_error(char *msg);
void app_error(char *msg);
/* Process control wrappers */
pid_t Fork(void);
void Execve(const char *filename, char *const argv[], char *const envp[]);
pid_t Wait(int *status);
pid_t Waitpid(pid_t pid, int *iptr, int options);
void Kill(pid_t pid, int signum);
unsigned int Sleep(unsigned int secs);
void Pause(void);
unsigned int Alarm(unsigned int seconds);
void Setpgid(pid_t pid, pid_t pgid);
pid_t Getpgrp();
/* Signal wrappers */
typedef void handler_t(int);
handler_t *Signal(int signum, handler_t *handler);
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
void Sigemptyset(sigset_t *set);
void Sigfillset(sigset_t *set);
void Sigaddset(sigset_t *set, int signum);
void Sigdelset(sigset_t *set, int signum);
int Sigismember(const sigset_t *set, int signum);
/* Unix I/O wrappers */
int Open(const char *pathname, int flags, mode_t mode);
ssize_t Read(int fd, void *buf, size_t count);
ssize_t Write(int fd, const void *buf, size_t count);
off_t Lseek(int fildes, off_t offset, int whence);
void Close(int fd);
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
int Dup2(int fd1, int fd2);
void Stat(const char *filename, struct stat *buf);
void Fstat(int fd, struct stat *buf) ;
/* Memory mapping wrappers */
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
void Munmap(void *start, size_t length);
/* Standard I/O wrappers */
void Fclose(FILE *fp);
FILE *Fdopen(int fd, const char *type);
char *Fgets(char *ptr, int n, FILE *stream);
FILE *Fopen(const char *filename, const char *mode);
void Fputs(const char *ptr, FILE *stream);
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
/* Dynamic storage allocation wrappers */
void *Malloc(size_t size);
void *Realloc(void *ptr, size_t size);
void *Calloc(size_t nmemb, size_t size);
void Free(void *ptr);
/* Sockets interface wrappers */
int Socket(int domain, int type, int protocol);
void Setsockopt(int s, int level, int optname, const void *optval, int optlen);
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen);
void Listen(int s, int backlog);
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
/* DNS wrappers */
struct hostent *Gethostbyname(const char *name);
struct hostent *Gethostbyaddr(const char *addr, int len, int type);
/* Pthreads thread control wrappers */
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void * (*routine)(void *), void *argp);
void Pthread_join(pthread_t tid, void **thread_return);
void Pthread_cancel(pthread_t tid);
void Pthread_detach(pthread_t tid);
void Pthread_exit(void *retval);
pthread_t Pthread_self(void);
void Pthread_once(pthread_once_t *once_control, void (*init_function)());
/* POSIX semaphore wrappers */
void Sem_init(sem_t *sem, int pshared, unsigned int value);
void P(sem_t *sem);
void V(sem_t *sem);
/* Rio (Robust I/O) package */
ssize_t rio_readn(int fd, void *usrbuf, size_t n);
ssize_t rio_writen(int fd, void *usrbuf, size_t n);
void rio_readinitb(rio_t *rp, int fd);
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
/* Wrappers for Rio package */
ssize_t Rio_readn(int fd, void *usrbuf, size_t n);
void Rio_writen(int fd, void *usrbuf, size_t n);
void Rio_readinitb(rio_t *rp, int fd);
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
/* Client/server helper functions */
int open_clientfd(char *hostname, int portno);
int open_listenfd(int portno);
/* Wrappers for client/server helper functions */
int Open_clientfd(char *hostname, int port);
int Open_listenfd(int port);
#endif /* __CSAPP_H__ */
/* $end csapp.h */
================================================
FILE: exercise/00-topic.txt
================================================
================================================================================
这个文件收集了《深入理解计算机系统·第二版》的家庭作业的题目。关于这本书的详细信
息如下:
深入理解计算机系统·第二版
Randal E. Bryant David R. O'Hallaron 著
龚奕利 雷迎春 译
机械工业出版社
2012 年 7 月第 1 版第 8 次印刷
================================================================================
2.55 在你能够访问的不同机器上,使用 show_bytes(文件 show-bytes.c)编译并运行示
例代码。确定这些机器使用的字节顺序。
2.56 试着用不同的示例值来运行 show_bytes 的代码。
2.57 编写程序 show_short、show_long 和 show_double,它们分别打印类型为 short int、
long int 和 double 的 C 语言对象的字节表示。请试着在几种机器上运行。
2.58 编写过程 is_little_endian,当在小端法机器上编译和运行时返回 1,在大端法机器
上编译运行时返回 0.这个程序应该可以运行在任何机器上,无论机器的字长是多少。
2.59 编写一个 C 表达式,使它生成一个字,由 x 的最低有效字节和 y 中剩下的字节组成。
对于运算数 x=0x89ABCDEF 和 y=0x76543210,就得到 0x765432EF。
2.60 假设我们将一个 w 位的字中的字节从 0(最低位)到 w/8-1(最高位)编号。写出下
面的代码,它会返回一个无符号值,其中参数 x 的字节 i 被替换成字节 b:
unsigned replace_byte(unsigned x, unsigned char b, int i);
以下的一些示例,说明了这个函数如何工作:
replace_byte(0x12345678, 0xAB, 2) --> 0x12AB5678
replace_byte(0x12345678, 0xAB, 0) --> 0x123456AB
位级整数编码规则
在接下来的作业中,我们特意限制了你能使用的编程结构,来帮你更好地理解 C 语言
的位级、逻辑和算数运算。在回答这些问题时,你的代码必须遵守下面这些规则:
o 假设
· 整数用补码形式表示。
· 有符号数的右移是算数右移。
· 数据类型 int 是 w 位长的。对于某些题目,会给定 w 的值,但是在其他情况下,
只要 w 是 8 的整数倍,你的代码就应该能工作。你可以用表达式
sizeof(int)<<3 来计算 w。
o 禁止使用
· 条件语句(if 或者 ?:)、循环、分支语句、函数调用和宏调用。
· 除法、模运算和乘法。
· 相对比较运算符(<、>、<=和>=)。
o 允许的运算
· 所有的位级和逻辑运算。
· 左移和右移,但是位移的数量只能在 0 和 w-1 之间。
· 加法和减法。
· 相等(==)和不相等(!=)测试。(在有些题目中。也不允许这些运算。)
· 整形常数 INT_MIN 和 INT_MAX。
· 强制类型转换,无论是显式的还是隐式的。
即使有这些条件的限制,你仍然可以选择描述性的变量名,并且使用注释来描述你的
解决方案的逻辑,尽量提高代码的可读性。例如,下面这段代码从整数参数 x 中抽取
出最高有效字节:
/* Get most significant byte from x */
int get_msb(int x) {
/* Shift by w-8 */
int shift_val = (sizeof(int)-1) << 3;
/* Arithmetic shift */
int xright = x >> shift_val;
/* Zero all but LSB */
return xright & 0xFF;
}
2.61 写一个 C 表达式,在下列描述的条件下产生 1,而在其他情况下得到 0。假设 x 是
int 类型。
A. x 的任何位都等于 1
B. x 的任何位都等于 0
C. x 的最高有效字节中的位都等于 1
D. x 的最低有效字节中的位都等于 0
代码应该遵循位级整数编码规则,另外还有一个限制,你不能使用相等(==)和不相
等(==)测试。
2.62 编写一个函数 int_shifts_are_logical(),在对 int 类型的数使用算术右移的机器
上运行时,这个函数生成 1,而其他情况下生成 0。你的代码应该可以运行在任何字
长的机器上。在几种机器上测试你的代码。
2.63 将下面的 C 函数代码补充完整。函数 srl 用算术右移(由值 xsra 给出)来完成逻
辑右移,后面的其他操作不包括右移或者除法。函数 sra 用逻辑右移(由值 xsrl 给
出)来完成算术右移,后面的其他操作不包括右移或者除法。可以通过计算
8*sizeof(int) 来确定数据类型 int 中的位数 w。位移量 k 的取值范围位 0~w-1。
int sra(int x, int k) {
/* Perform shift logically */
int xsrl = (unsigned) x >> k;
.
.
.
}
unsigned srl(unsigned x, int k) {
/* Perform shift arithmetically */
unsigned xsra = (int) x >> k;
.
.
.
}
2.64 写出代码实现如下函数:
/* Return 1 when any even bit of x equals 1; 0 otherwise.
Assume w=32 */
int any_even_one(unsigned x);
函数应该遵循位级整数编码规则,不过你可以假设数据类型 int 有 w=32 位。
2.65 写出代码实现如下函数:
/* Return 1 when x contains an even number of 1s; 0 otherwise.
Assume w=32 */
int even_ones(unsigned x);
函数应该遵循位级编码规则,不过你可以假设数据类型 int 有 w=32 位。
你的代码最多只能包含 12 个算术运算、位运算和逻辑运算。
2.66 写出代码实现如下的函数:
/*
* Generate mask indicating leftmost 1 in x. Assume w=32.
* For example 0xFF00 -> 0x8000, and 0x6600 --> 0x4000.
* If x = 0, then return 0.
*/
int leftmost_one(unsigned x);
函数应该遵循位级整数编码规则,不过你可以假设数据类型 int 有 w=32 位。
你的代码最多只能包含 15 个算数运算、位运算和逻辑运算。
提示:先将 x 转换成形如 [0...011...1] 的位向量。
2.67 给你一个任务,编写一个过程 int_size_is_32(),当在一个 int 是 32 位的机器上
运行时,该程序产生 1,而其他情况则产生 0。不允许使用 sizeof 运算符。下面是
开始时的尝试:
/* The following code does not run properly on some machines */
int bad_int_size_is_32() {
/* Set most significant bit (msb) of 32-bit machine */
int set_msb = 1 << 31;
/* Shift past msb of 32-bit word */
int beyond_msb = 1 << 32;
/* set_msb is nonzero when word size >= 32
beyond_msb is zero when word size <= 32 */
return set_msb && !beyond_msb;
}
当在 SUN SPARC 这样的 32 位机器上编译并运行时,这个过程返回的却是 0。下面的
编译器信息给了我们一个问题的指示:
warning: left shift count >= width of type
A. 我们的代码在哪个方面没有遵守 C 语言标准?
B. 修改代码,使得它在 int 至少为 32 位的任何机器上都能正确运行。
C. 修改代码,使得它在 int 至少位 16 位的任何机器上都能正确运行。
2.68 写出具有如下原型的函数的代码:
/*
* Make with least signficant n bits set to 1
* Examples: n=6 --> 0x3f, n=17 --> 0x1FFFF
* Assume 1 <= n <= w
*/
int lower_bits(int x, int n);
函数应该遵循位级整数编码规则。要注意 n = w 的情况。
2.69 写出具有如下原型的函数的代码:
/*
* Do rotating right shift. Assume 0 <= n < w
* Examples when x = 0x12345678 and w = 32:
* n=4 -> 0x81234567, n=20 -> 0x45678123
*/
unsigned rotate_right(unsigned x, int n);
函数应该遵循位级整数编码规则。要注意 n = 0 的情况。
2.70 写出具有如下原型的函数的代码:
/*
* Return 1 when x can be represented as an n-bit, 2's complement
* number; 0 otherwise
* Assume 1 <= n <= w
*/
int fits_bits(int x, int n);
函数应该遵循位级整数编码规则。
2.71 你刚刚开始在一家公司工作,他们要实现一组过程来操作一个数据结构,要将 4 个有
符号字节封装成一个 32 位 unsigned。一个字中的字节从 0(最低有效字节)编号到
3(最高有效字节)。分配给你的任务是:为一个使用补码运算和算数右移的机器编写
一个具有如下原型的函数:
/* Declaration of data type where 4 bytes are packed
into an unsigned */
typedef unsigned packed_t;
/* Extract byte from word. Return as signed integer */
int xbyte(packed_t word, int bytenum);
也就是说,函数会抽取出指定的字节,再把它符号扩展为一个 32 位 int。你的前任
(因为水平不够高而被解雇了)编写了下面的代码:
/* Failed attempt at xbyte */
int xbyte(packed_t word, int bytenum)
{
return (word >> (bytenum << 3)) & 0xFF;
}
A. 这段代码错在哪里?
B. 给出函数的正确实现,只能使用左右移位和一个减法。
2.72 给你一个任务,写一个函数,将整数 val 复制到缓冲区 buf 中,但是只有缓冲区
buf 中,但是只有当缓冲区中有足够可用的空间时,才执行复制。
你写的代码如下:
/* Copy integer into buffer if space is available */
/* WARNING: The following code is buggy */
void copy_int(int val, void *buf, int maxbytes) {
if (maxbytes-sizeof(val) >= 0)
memcpy(buf, (void *)&val, sizeof(val));
}
这段代码使用了库函数 memcpy。虽然在这里用这个函数有点刻意,因为我们只是想复
制一个 int,但是说明了一种复制较大数据结构的常见方法。
你仔细地测试了这段代码后发现,哪怕 maxbytes 很小的时候,它也能把值复制到缓
冲区中。
A. 解释为什么代码中的条件测试总是成功。提示:sizeof 运算符返回类型为 size_t 的值。
B. 你该如何重写这个条件测试,使之工作正确。
2.73 写出具有如下原型的函数的代码:
/* Addition that saturates to TMin or TMax */
int saturating_add(int x, int y);
同正常的补码溢出的方式不同,当正溢出时,saturating_add 返回 TMax,负溢出时,
返回 TMin。这种运算常常用在执行数字信号处理的程序中。
你的函数应该遵循位级整数编码规则。
2.74 写出具有如下原型的函数的代码:
/* Determine whether subtracting arguments will cause overflow */
int tsub_ovf(int x, int y);
如果计算 x-y 导致溢出,这个函数就返回 1。
2.75 假设我们想要计算 x·y 的完整的 2w 位表示,其中,x 和 y 都是无符号数,并且运
行在数据类型 unsigned 是 w 位的机器上。乘积的低 w 位能够用表达式 x·y 计算,
所以,我们只需要一个具有下列原型的函数:
unsigned unsigned_high_prod(unsigned x, unsigned y);
这个函数计算无符号变量 x·y 的高 w 位。
我们使用一个具有下面原型的库函数:
int signed_high_prod(int x, int y);
它计算在 x 和 y 采用补码形式的情况下,x·y 的高 w 位。编写代码调用这个过程,
以实现用无符号数为参数的函数。验证你的解答的正确性。
提示:看看等式(2-18)的推导中,有符号乘积 x·y 和无符号乘积 x'·y' 之间的关
系。
2.76 假设我们有一个任务:生成一段代码,将整数变量 x 乘以不同的常数因子 K。为了提
高效率,我们想只使用 +、- 和 << 运算。对于下列的 K 的值,写出执行乘法运算的
C 表达式,每个表达式中最多使用 3 个运算。
A. K=5
B. K=9
C. K=30
D. K=-56
2.77 写出具有如下原型的函数的代码:
/* Divide by power of two. Assume 0 <= k < w-1 */
int divide_power2(int x, int k);
该函数要用正确的舍入计算 x/2^k,并且应该遵循位级整数编码规则。
2.78 写出函数 mul5div8 的代码,对于整数参数 x,计算 5*x/8,但是要遵循位级整数编
码规则。你的代码计算 5*x 也会产生溢出。
2.79 写出函数 fiveeighths 的代码,对于整数参数 x,计算 5/8x 的值,向零舍入。它不
会溢出。函数应该遵循整数位级编码规则。
2.80 编写 C 表达式产生如下位模式,其中 a^n 表示符号 a 重复 n 次。假设一个 w 位的
数据类型。你的代码可以包含对参数 m 和 n 的引用,它们分别表示 m 和 n 的值,但
是不能使用表示 w 的参数。
A. 1^(w-n)0^n
B. 0^(w-n-m)1^n0^m
2.81 我们在一个 int 类型值为 32 位的机器上运行程序。这些值以补码形式表示,而且它
们都是算术右移的。unsigned 类型的值也是 32 位的。
我们产生随机数 x 和 y,并且把它们转换成无符号数,显示如下:
/* Create some arbitrary values */
int x = random();
int y = random();
/* Convert to unsigned */
unsigned ux = (unsigned) x;
unsigned uy = (unsigned) y;
对于下列每个 C 表达式,你要指出表达式是否总是为 1。如果它总是为 1,那么请描
述其中的数学原理。否则,列举一个使它为 0 的参数示例。
A. (x > y) == (-x < -y)
B. ((x + y) << 5) + x - y == 31 * y + 33 * x
C. ~x + ~y == ~(x + y)
D. (int)(ux - uy) == -(y - x)
E. ((x >> 1) << 1) <= x
2.82 一些数字的二进制表示是由形如 0.yyyyyy... 的无穷串组成的,其中 y 是一个 k 位
的序列。例如,1/3 的二进制表示是 0.01010101...(y=01),而 1/5 的二进制表示
是0.001100110011(y=0011)。
A. 设 Y=B2Uk(y),也就是说,这个数具有二进制表示 y。给出一个由 Y 和 k 组成的
公式表示这个无穷串的值。提示:请考虑将二进制小数点右移 k 位的结果。
B. 对于下列 y 的值,串的数值是多少?
(a) 001
(b) 1001
(c) 000111
2.83 填写下列程序的返回值,这个程序是测试它的第一个参数是否大于或者等于第二个参
数。假定函数 f2u 返回一个无符号 32 位数字,其位表示与它的浮点参数相同。你可
以假设两个参数都不是 NaN。两种 0,+0 和 -0 都认为是相等的。
int float_ge(float x, float y) {
unsigned ux = f2u(x);
unsigned uy = f2u(y);
/* Get the sign bits */
unsigned sx = ux >> 31;
unsigned sy = uy >> 31;
/* Given an expression using only ux, uy, sx, sy */
return ________;
}
2.84 给定一个浮点格式,有 k 位指数和 n 位小数,对于小列数,写出阶码 E、尾数 M、
小数 f 和值 V 的公式。另外,请描述其位表示。
A. 数 5.0。
B. 能够被准确描述的最大奇整数。
C. 最小的规格化数的倒数。
2.85 与 Intel 兼容的处理器也支持“扩展精度”浮点形式,这种格式具有 80 位字长,被
分成 1 个符号位、k = 15 个阶码位、1 个单独的整数位和 n = 63 个小数位。整数
位是 IEEE 浮点表示中隐含位的显式副本。也就是说,对于规格化的值它等于 1,对
于非规格化的值它等于 0。填写小表,给出用这种格式表示的一些“有趣的”数字的
近似值。
| 描述 | 扩展精度 | |
| | 值 | 十进制 |
| 最小的正非规格化数 | | |
| 最小的正规格化数 | | |
| 最大的规格化数 | | |
2.86 考虑一个基于 IEEE 浮点格式的 16 位浮点表示,它具有 1 个符号位、7 个阶码位
(k=7)和 8 个小数位(n=8)。阶码偏置量是 2^(7-1)-1 = 63。
对于每个给定的数,填写下表,其中每一列具有如下指示说明:
Hex: 描述编码形式的 4 个十六进制数字。
M: 尾数的值。这应该是一个形如 x 或 x/y 的数,其中 x 是一个整数,而 y 是 2
的整数幂。例如,0、67/64 和 1/25。
E: 阶码的整数值。
V: 所表示的数字值。使用 x 或者 x * 2^z 表示,其中 x 和 z 都是整数。
举一个例子,为了表示 7/2,我们有 s=0,M=7/4 和 E=1。因此这个数的阶码字段为
0x40(十进制值 63+1=64),尾数字段为 0xC0(二进制 1100 0000_2),得到一个十
六进制的表示 40C0。
标记为“--”的条目不用填写。
|--------------------------+-----+----+----+----|
| 描述 | Hex | M | E | V |
|--------------------------+-----+----+----+----|
| -0 | | | | -- |
| 最小的值 >1 | | | | |
| 256 | | | | -- |
| 最大的非规格化数 | | | | |
| -oo | | -- | -- | -- |
| 十六进制表示为 3AA0 的数 | | | | |
|--------------------------+-----+----+----+----|
2.87 考虑下面两个基于 IEEE 浮点格式的 9 位浮点表示。
1. 格式 A
o 有一个符号位
o 有 k=5 个阶码位。阶码偏置量是 15。
o 有 n=3 个小数位。
2. 格式 B
o 有一个符号位
o 有 k=4 个阶码位。阶码偏置量是 7。
o 有 n=4 个小数位。
下面给出了一些格式 A 表示的位模式,你的任务是把它们转换成最接近的格式 B 表
示的值。如果需要舍入,你要向 +oo 舍入。另外,给出格式 A 和格式 B 表示的位模
式对应的值。要么是整数(例如,17),要么是小数(例如,17/64 或 17/2^6)。
|-------------+-------+-------------+-------|
| 格式A | | 格式B | |
|-------------+-------+-------------+-------|
| 位 | 值 | 位 | 值 |
|-------------+-------+-------------+-------|
| 1 01110 001 | -9/16 | 1 0110 0010 | -9/16 |
| 0 10110 101 | | | |
| 1 00111 110 | | | |
| 0 00000 101 | | | |
| 1 11011 000 | | | |
| 0 11000 100 | | | |
|-------------+-------+-------------+-------|
2.88 我们在一个 int 类型为 32 位补码表示的机器上运行程序。float 类型的值使用 32
位 IEEE 格式,而 double 类型的值使用 64 位 IEEE 格式。
我们产生随机数 x、y 和 z,并且把它们转换成 double 类型的值:
/* Create some arbitrary values */
int x = random();
int y = random();
int z = random();
/* Convert to double */
double dx = (double)x;
double dy = (double)y;
double dz = (double)z;
对于下列的每个 C 表达式,你要指出表达式是否总是为 1。如果它总是为 1,描述其
中的数学原理。否则,列举出使它为 0 的参数的例子。请注意,不能使用 IA32 机器
运行 GCC 来测试你的答案,因为对于 float 和 double,它使用的都是 80 位的扩展
精度表示。
A. (double)(float)x == dx
B. dx + dy == (double)(x+y)
C. dx + dy + dz == dz + dy + dx
D. dx * dy * dz == dz * dy * dx
E. dx / dx == dy / dy
2.89 分配给你一个任务,编写一个 C 函数来计算 2^x 的浮点表示。你意识到完成这个任
务的最好方法是直接创建结果的 IEEE 单精度表示。当 x 太小时,你的程序将返回
0.0。当 x 太大时,它会返回 +oo。填写下列代码的空白部分,以计算出正确的结果。
假设函数 u2f 返回的浮点值与它的无符号参数有相同的位表示。
2.90 大约在公元前 250 年,希腊数学家阿基米德证明了 223/71 < PI < 22/7。如果当时
有一台计算机和标准库 <math.h>,他就能够确定 n 的单精度浮点近似值的十六进制
表示为 0x40490FDB。当然,所有的这些都只是近似值,因为 PI 不是有理数。
A. 这个浮点值表示的二进制小数是多少?
B. 22/7 的二进制小数表示是什么?提示:参见家庭作业 2.82。
C. 这两个 22/7 的近似值从哪一位(相对于二进制小数点)开始不同的?
位级浮点编码规则
在接下来的题目中,你要写的代码要实现浮点函数在浮点数的位级表示上直接运算。
你的代码应该完全遵循 IEEE 浮点运算的规则,包括当需要舍入时,要使用向偶数舍
入的方式。为此,我们定义数据类型 float_bits 等价于 unsigned:
/* Access bit-level representation floating-point number */
typedef unsigned float_bits;
你的代码中不使用数据类型 float,而要使用 float_bits。你可以使用数据类型 int
和 unsigned,包括无符号和整数常数和运算。你不可以使用任何联合、结构和数组。
更重要的是,你不能使用任何浮点数据类型、运算或者常数。取而代之的是,你的代
码应该执行实现这些指定的浮点运算的位操作。
下面的函数说明了对这些规则的使用。对于参数 f,如果 f 是非规格化的,该函数返
回 ±0(保持 f 的符号),否则,返回 f。
/* If f is denorm, return 0. Otherwise, return f */
float_bits float_denorm_zero(float_bits f) {
/* Decompose bit representation into parts */
unsigned sign = f>>31;
unsigned exp = f>>23 & 0xFF;
unsigned frac = f & 0x7FFFFF;
if (exp == 0) {
/* Denormalized. Set fraction to 0 */
frac = 0;
}
/* Reassemble bits */
return (sign << 31) | (exp << 23) | frac;
}
2.91 遵循位级浮点编码规则,实现具有如下原型的函数:
/* Compute |f|. If f is NaN, then return f. */
float_bits float_absval(float_bits f);
对于浮点数 f,这个函数计算 |f|。如果 f 是 NaN,你的函数应该简单地返回 f。测
试你的函数,对参数 f 可以取的所有 2^32 个值求值,将结果与你实用机器的浮点运
算得到的结果相比较。
2.92 遵循位级浮点编码规则,实现具有如下原型的函数:
/* Compute -f. If f is Nan, then return f. */
float_bits float_negate(float_bits f);
对于浮点数 f,这个函数计算 -f。如果 f 是 NaN,你的函数应该简单地返回 f。测试
你的函数,对参数 f 可以取的所有 2^32 个值求值,将结果与你使用机器的浮点运算
得到的结果相比较。
2.93 遵循位级浮点编码规则,实现具有如下原型的函数:
/* Compute 0.5*f. If f is NaN, then return f. */
float_bits float_half(float_bits f);
对于浮点数 f,这个函数计算 0.5*f。如果 f 是 NaN,你的函数应该简单返回 f。测
试你的函数,对参数 f 可以取的所有 2^32 个值求值,将结果与你使用机器的浮点运
算得到的结果相比较。
2.94 遵循位级浮点编码规则,实现具有如下原型的函数:
/* Compute 2*f. If f is NaN, then return f. */
float_bits float_twice(float_bits f);
对于浮点数 f,这个函数计算 2.0*f。如果 f 是 NaN,你的函数应该简单地返回 f。
测试你的函数,对参数 f 可以取的所有 2^32 个值求值,将结果与你使用机器的浮点
运算得到的结果相比较。
2.95 遵循位级浮点编码规则,实现具有如下原型的函数:
/* Compute (float) i */
float_bits float_i2f(int i);
对于参数 i,这个函数计算 (float)i 的位级表示。
测试你的函数,对参数 f 可以取的所有 2^32 个值求值,将结果与你使用机器的浮点
运算得到的结果相比较。
2.96 遵循位级浮点编码规则,实现具有如下原型的函数:
/*
* Compute (int) f.
* If conversion causes overflow or f is NaN, return 0x80000000
*/
int float_f2i(float_bits f);
对于浮点数 f,这个函数计算 (int)f。你的函数应该向零舍入。如果f 不能用整数表示
(例如,超出表示范围,或者它是一个 NaN),那么函数应该返回0x80000000。测试你
的函数,对参数 f 可以取的所有 2^32 个值求值,将结果与你使用机器的浮点运算得到
的结果相比较。
3.54 一个函数的原型为
int decode2(int x, int y, int z);
将这个函数编译成 IA32 汇编代码。代码体如下:
# x at %ebp+8, y at %ebp+12, z at %ebp+16
1 movl 16(%ebp), %edx
2 subl 12(%ebp), %edx
3 movl %edx, %eax
4 sall $15, %eax
5 sarl $15, %eax
6 xorl 8(%ebp), %edx
7 imull %edx, %eax
参数 x、y 和 z 存放在存储器中相对于寄存器 %ebp 中地址偏移量为 8、12 和 16
的地方。代码将返回值存放在寄存器 %eax 中。
写出等价于我们汇编代码的 decode2 的 C 代码。
3.55 下面的代码计算 x 和 y 的乘积,并将结果存放在存储器中。数据类型 ll_t 被定义
为等价于 long long。
typedef long long ll_t;
void store_prod(ll_t *dest, ll_t x, int y)
{
*dest = x * y;
}
GCC 生成下面的汇编代码实现计算:
# dest at %ebp+8, x at %ebp+12, y at %ebp+20
1 movl 12(%ebp), %esi
2 movl 20(%ebp), %eax
3 movl %eax, %edx
4 sarl $31, %edx
5 movl %edx, %ecx
6 imull %esi, %ecx
7 movl 16(%ebp), %ebx
8 imull %eax, %ebx
9 addl %ebx, %ecx
10 mull %esi
11 leal (%ecx, %edx), %edx
12 movl 8(%ebp), %ecx
13 movl %eax, (%ecx)
14 movl %edx, 4(%ecx)
这段代码用了三个乘法来实现多精度运算,这个多精度运算是在 32 位机器上实现 64
位运算所需要的。描述用来计算这个乘积的算法,并对汇编代码添加注释,说明它是
如何实现你的算法的。
提示:参考练习题 3.12 及其答案。
3.56 考虑下面的汇编代码:
# x at %ebp+8, n at %ebp+12
1 movl 8(%ebp), %esi
2 movl 12(%ebp), %ebx
3 movl $1431655765, %edi
4 movl $-2147483648, %edx
5 .L2:
6 movl %edx, %eax
7 andl %esi, %eax
8 xorl %eax, %edi
9 movl %ebx, %ecx
10 shrl %cl, %edx
11 testl %edx, %edx
12 jne .L2
13 movl %edi, %eax
以上代码是以下整体形式的 C 代码编译产生的:
1 int loop(int x, int n)
2 {
3 int result = ____;
4 int mask;
5 for (mask = ____; mask ____; mask = ____) {
6 result ^= ____;
7 }
8 return result;
9 }
你的任务是填写这个 C 代码中缺失的部分,得到一个程序等价于产生的汇编代码。回
想一下,这个函数的结果是在寄存器 %eax 中返回的。你会发现以下工作很有帮助:
检查循环之前、之中和之后的汇编代码,形成一个寄存器和程序变量之间一致的映射。
A. 哪个寄存器保存着程序值 x、n、result 和 mask?
B. result 和 mask 的初始值是什么?
C. mask 的测试条件是什么?
D. mask 是如何被修改的?
E. result 是如何被修改的?
F. 填写这段 C 代码中所有缺失的部分。
3.57 在 3.6.6 节,我们查看了下面的代码,作为使用条件数据传输的一种选择:
int cread(int *xp) {
return (xp ? *xp : 0);
}
我们给出了使用条件传送指令的一个尝试实现,但是认为它是不合法的,因为它试图
从一个空地址读数据。
写一个 C 函数 cread_alt,它与 cread 有一样的行为,除了它可以被编译成使用条
件数据传送。当用命令行选项 '-march=i686' 来编译时,产生的代码应该使用条件传
送指令而不是某种跳转指令。
3.58 下面的代码是在一个开关语句中根据枚举类型值进行分支选择的例子。回忆一下,C
语言中枚举类型只是一种引入一组与整数值相对应的名字的方法。默认情况下,值是
从 0 向上依次赋给名字的。在我们的代码中,省略了与各种情况标号相对应的动作。
/* Enumerated type creates set of constants numbered 0 and upward */
typedef enum { MODE_A, MODE_B, MODE_C, MODE_D, MODE_E } mode_t;
int switch3(int *p1, int *p2, mode_t action)
{
int result = 0;
switch (action) {
case MODE_A:
case MODE_B:
case MODE_C:
case MODE_D:
case MODE_E:
default:
}
return result;
}
产生的实现各个动作的汇编代码部分如下所示。注释指明了参数位置,寄存器值,以
及各个跳转目的的情况标号。寄存器 %edx 对应于程序变量 result,并被初始化为
-1。填写 C 代码中缺失的部分。注意那些会落入其他情况中的情况。
# Arguments: p1 at %ebp+8, p2 at %ebp+12, action at %ebp+16
# Registers: result in %edx (initialized to -1)
# The jump targets:
1 .L17: # MODE_E
2 movl $17, %edx
3 jmp .L19
4 .L13: # MODE_A
5 movl 8(%ebp), %eax
6 movl (%eax), %edx
7 movl 12(%ebp), %ecx
8 movl (%ecx), %eax
9 movl 8(%ebp), %ecx
10 movl %eax, (%ecx)
11 jmp .L19
12 .L14: # MODE_B
13 movl 12(%ebp), %edx
14 movl (%edx), %eax
15 movl %eax, %edx
16 movl 8(%ebp), %ecx
17 addl (%ecx), %edx
18 movl 12(%ebp), %eax
19 movl %edx, (%eax)
20 jmp .L19
21 .L15: # MODE_C
22 movl 12(%ebp), %edx
23 movl $15, (%edx)
24 movl 8(%ebp), %ecx
25 movl (%ecx), %edx
26 jmp .L19
27 .L16: # MODE_D
28 movl 8(%ebp), %edx
29 movl (%edx), %eax
30 movl 12(%ebp), %ecx
31 movl %eax, (%ecx)
32 movl $17, %edx
33 .L19: # default
34 movl %edx, %eax # Set return value
上面的代码实现了 switch 语句的各个分支
3.59 这个程序给你一个机会,逆向工程一个 switch 语句。在下面这个过程中,去掉了
switch 语句的主体:
int switch_prob(int x, int n)
{
int result = x;
switch (n) {
/* Fill in code here */
}
return result;
}
下面给出了这个过程的反汇编机器代码。我们可以看到,在第 4 行,参数 n 被加载
到寄存器 %eax 中。
1 08048420 <switch_prob>:
2 8048420: 55 push %ebp
3 8048421: 89 e5 mov %esp, %ebp
4 8048423: 8b 45 0c mov 0xc(%ebp), %eax
5 8048426: 83 e8 28 sub $0x28, %eax
6 8048429: 83 f8 05 cmp $0x5, %eax
7 804842c: 77 07 ja 8048435 <switch_prob+0x15>
8 804842e: ff 24 85 f0 85 04 08 jmp *0x80485f0(,%eax,4)
9 8048435: 8b 45 08 mov 0x8(%ebp), %eax
10 8048438: eb 24 jmp 804845e <switch_prob+0x3e>
11 804843a: 8b 45 08 mov 0x8(%ebp), %eax
12 804843d: 8d 76 00 lea 0x0(%esi), %esi
13 8048440: eb 19 jmp 804845b <switch_prob+0x3b>
14 8048442: 8b 45 08 mov 0x8(%ebp), %eax
15 8048445: c1 e0 03 shl $0x3, %eax
16 8048448: eb 17 jmp 8048461 <switch_prob+0x41>
17 804844a: 8b 45 08 mov 0x8(%ebp), %eax
18 804844d: c1 f8 03 sar $0x3, %eax
19 8048450: eb 0f jmp 8048461 <switch_prob+0x41>
20 8048452: 8b 45 08 mov 0x8(%ebp), %eax
21 8048455: c1 e0 03 shl $0x3, %eax
22 8048458: 2b 45 08 sub 0x8(%ebp), %eax
23 804845b: 0f af c0 imul %eax, %eax
24 804845e: 83 c0 11 add $0x11, %eax
25 8048461: 5d pop %ebp
26 8048462: c3 ret
跳转表驻留在另一个存储器区域中。可以从第 8 行的间接跳转看出,跳转表的起始地
址为 0x80485f0。用调试器 GDB,我们可以用命令 x/6w 0x80485f0 来检查存储器中
的 6 个 4 字节的字。GDB 打印下面的内容:
(gdb) x/6w 0x80485f0
0x80485f0: 0x08048442 0x08048435 0x08048442 0x0804844a
0x8048600: 0x08048452 0x0804843a
用 C 代码填写开关语句的主体,使它的行为与机器代码一致。
3.60 考虑下面的源代码,这里 R、S 和 T 都是用 #define 声明的常数:
int A[R][S][T];
int store_ele(int i, int j, int k, int *dest)
{
*dest = A[i][j][k];
return sizeof(A);
}
编译这个程序,GCC 产生下面的汇编代码:
; i at %ebp+8, j at %ebp+12, k at %ebp+16, dest at %ebp+20
1 movl 8(%ebp), %ecx
2 movl 12(%ebp), %eax
3 leal (%eax,%eax,8), %eax
4 movl %ecx, %edx
5 sall $6, %edx
6 subl %ecx, %edx
7 addl %edx, %eax
8 addl 16(%ebp), %eax
9 movl A(,%eax,4), %edx
10 movl 20(%ebp), %eax
11 movl %edx, (%eax)
12 movl $2772, %eax
A. 将等式(3-1)从二维扩展到三维,提供数组元素 A[i][j][k] 的位置的公式。
B. 运用你的逆向工程技术,根据汇编代码,确定 R、S 和 T 的值。
3.61 C 编译器为 var_prod_ele 产生的代码不能将它在循环中使用的所有值都放进寄存器中,
因此它必须在每次循环时都从存储器中读出 n 的值。写出这个函数的 C 代码,使用类
似于 GCC 执行的那些优化,但是它的编译代码不会让循环值溢出到存储器中。
/* Compute i,k of variable matrix product */
int var_prod_ele(int n, int A[n][n], int B[n][n], int i, int k)
{
int j;
int result = 0;
for (j = 0; j < n; j++)
result += A[i][j] * B[j][k];
return result;
}
回忆一下,处理器只有 6 个寄存器可用来保存临时数据,因为寄存器 %ebp 和 %esp
不能用于此目的。其中一个寄存器还必须用来保存乘法指令的结果。因此,你必须把
循环中的值的数量从 6 个(result、Arow、Bcol、j、n 和 4*n)减少到 5 个。
需要找到一个对你那种编译器行之有效的策略。不断尝试各种不同的策略,直到有一
种能工作。
3.62 下面的代码转置一个 MxM 矩阵的元素,这里 M 是一个用 #define 定义的常数:
void transpose(int A[M][M])
{
int i,j;
for (i = 0; i < M; i++)
for (j = 0; j < i; j++) {
int t = A[i][j];
A[i][j] = A[j][i];
A[j][i] = t;
}
}
当用优化等级 -O2 编译时,GCC 为这个函数的内部循环产生下面的代码:
1 .L3:
2 movl (%ebx), %eax
3 movl (%esi,%ecx,4), %edx
4 movl %eax, (%esi,%ecx,4)
5 addl $1, %ecx
6 movl %edx, (%ebx)
7 addl $76, %ebx
8 cmpl %edi, %ecx
9 jl .L3
A. M 的值是多少?
B. 哪个寄存器保持着程序值 i 和 j?
C. 写 transpose 的一个 C 代码版本,使用在这个循环中出现的优化。在你的代码中,
使用参数 M,而不要使用常数值。
3.63 考虑下面的源代码,这里 E1 和 E2 是用 #define 声明的宏表达式,计算用参数 n
表示的矩阵 A 的维度。这段代码计算矩阵的第 j 列的元素之和。
int sum_col(int n, int A[E1(n)][E2(n)], int j)
{
int i;
int result = 0;
for (i = 0; i < E1(n); i++)
result += A[i][j];
return result;
}
编译这个程序,GCC 产生下面的汇编代码:
; n at %ebp+8, A at %ebp+12, j at %ebp+16
1 movl 8(%ebp), %edx
2 leal (%edx,%edx), %eax
3 leal -1(%eax), %ecx
4 leal (%eax,%edx), %esi
5 movl $0, %eax
6 testl %esi, %esi
7 jle .L3
8 leal 0(,%ecx,4), %ebx
9 movl 16(%ebp), %eax
10 movl 12(%ebp), %edx
11 leal (%edx,%eax,4), %ecx
12 movl $0, %edx
13 movl $0, %eax
14 .L4:
15 addl (%ecx), %eax
16 addl $1, %edx
17 addl %ebx, %ecx
18 cmpl %esi, %edx
19 jl .L4
20 .L3:
运用你的逆向工程技术,确定 E1 和 E2 的定义。
3.64 这个作业要查看 GCC 为参数和返回值中有结构的函数产生的代码,由此可以看到通常
这些语句特性是如何实现的。
下面的 C 代码是函数 word_sum,它用结构作为参数和返回值,还有一个函数 diff
调用 word_sum。
typedef struct {
int *p;
int v;
} str1;
typedef struct {
int prod;
int sum;
} str2;
str2 word_sum(str1 s1)
{
str2 result;
result.prod = *s1.p * s1.v;
result.sum = *s1.p + s1.v;
return result;
}
int diff(int x, int y)
{
str1 s1;
str2 s2;
s1.p = &x;
s1.v = y;
s2 = word_sum(s1);
return s2.prod - s2.sum;
}
GCC 为这两个函数产生下面的代码:
1 word_sum: 1 diff:
2 pushl %ebp 2 pushl %ebp
3 movl %esp, %ebp 3 movl %esp, %bp
4 pushl %ebx 4 subl $20, %esp
5 movl 8(%ebp), %eax 5 leal -8(%ebp), %edx
6 movl 16(%ebp), %ebx 6 leal 8(%ebp), %eax
7 movl 12(%ebp), %edx 7 movl %eax, 4(%esp)
8 movl (%edx), %edx 8 movl 12(%ebp), %eax
9 leal (%edx,%ebx), %ecx 9 movl %eax, 8(%esp)
10 movl %ecx, 4(%eax) 10 movl %edx, (%esp)
11 imull %ebx, %edx 11 call word_sum
12 movl %edx, (%eax) 12 subl $4, %esp
13 popl %ebx 13 movl -8(%ebp), %eax
14 popl %ebp 14 subl -4(%ebp), %eax
15 ret $4 15 leave
16 16 ret
指令 ret $4 很像普通的返回指令,但是它将栈指针增加了 8(4 个是为了返回地址,
加上 4 的加法),而不是 4。
A. 从 word_sum 代码的第 5~7 行我们可以看到,虽然函数只有一个参数,但是看上
去好像从栈中取出了 3 个值。描述这三个值分别是什么。
B. 从 diff 代码的第 4 行我们可以看到,栈桢中分配了 20 个字节。把他们当作 5
个字段来使用,每个字段 4 个字节。描述每个字段都是怎么用的。
C. 你要如何描述向函数传递结构参数的通用策略?
D. 你要如何描述处理从函数返回结构值的通用策略?
3.65 在下面的代码中,A 和 B 是用 #define 定义的常数:
typedef struct {
short x[A][B]; /* Unknown constants A and B */
int y;
} str1;
typedef struct {
char array[B];
int t;
short s[B];
int u;
} str2;
void setVal(str1 *p, str2 *q)
{
int v1 = q->t;
int v2 = q->u;
p->y = v1 + v2;
}
GCC 为 setVal 的主体产生下面的代码:
movl 12(%ebp), %eax
movl 28(%eax), %edx
addl 8(%eax), %edx
movl 8(%ebp), %eax
movl %edx, 44(%eax)
A 和 B 的值是多少?(答案是唯一的。)
3.66 你负责维护一个大型的 C 程序时,遇到下面这样的代码:
1 typedef struct {
2 int left;
3 a_struct a[CNT];
4 int right;
5 } b_struct;
6
7 void test(int i, b_struct *bp)
8 {
9 int n = bp->left + bp->right;
10 a_struct *ap = &bp->a[i];
11 ap->x[ap->idx] = n;
12 }
编译时常数 CNT 和结构 a_struct 的声明在一个你没有访问权限的文件中。幸好,你有代
码的'.o'版本,可以用 objdump 程序来反汇编这些文件,得到下面的反汇编代码:
1 00000000 <test>:
2 0: 55 push %ebp
3 1: 89 e5 mov %esp, %ebp
4 3: 53 push %ebx
5 4: 8b 45 08 mov 0x8(%ebp), %eax
6 7: 8b 4d 0c mov 0xc(%ebp), %ecx
7 a: 6b d8 1c imul $0x1c, %eax, %ebx
8 d: 8d 14 c5 00 00 00 00 lea 0x0(,%eax,8), %edx
9 14: 29 c2 sub %eax, %edx
10 16: 03 54 19 04 add 0x4(%ecx,%ebx,1), %edx
11 1a: 8b 81 c3 00 00 00 mov 0xc8(%ecx), %eax
12 20: 03 01 add (%ecx), %eax
13 22: 89 44 91 08 mov %eax, 0x8(%ecx,%edx,4)
14 25: 5b pop %ebx
15 27: 5d pop %ebp
16 28: c3 ret
运用你的逆向工程技术,推断下列的内容:
A. CNT 的值
B. 结构 a_struct 的完成声明。假设这个结构只有字段 idx 和 x。
3.67 考虑下面的联合声明:
union ele {
struct {
int *p;
int x;
} e1;
struct {
int y;
union ele *next;
} e2;
};
这个声明说明联合中可以嵌套结构。
下面的过程(省略了一些表达式)对一个链表进行操作,链表是以上述联合作为元素的:
void proc(union ele *up)
{
up->____ = *(up->____) - up->____;
}
A. 小列字段的偏移量是多少(以字节为单位):
e1.p: ____
e2.x: ____
e2.y: ____
e2.next: ____
B. 这个结构总共需要多少个字节?
C. 编译器为 proc 的主体产生下面的汇编代码:
; up at %ebp+8
1 movl 8(%ebp), %edx
2 movl 4(%edx), %ecx
3 movl (%ecx), %eax
4 movl (%eax), %eax
5 subl (%edx), %eax
6 movl %eax, 4(%ecx)
在这些信息的基础上,填写 proc 代码中缺失的表达式。提示:有些联合引用的解释可以有
歧义。当你清楚引用指引到哪里的时候,就能够澄清这些歧义。只有一个答案,不需要进行
强制类型转换,且不违反任何类型限制。
3.68 写一个函数 good_echo,它从标准输入读取一行,再把它写到标准输出。你的实现应
该对任意长度的输入行都能工作。可以使用库函数 fgets,但是你必须确保即使当输
入行要求比你应该为缓冲区分配的更多的空间时,你的函数也能正确地工作。你的代
码还应该检查错误条件,要在遇到 1 时返回。参考标准 I/O 函数的定义文档[48, 58]。
3.69 下面的声明定义了一类结构,用来构建二叉树:
1 typedef struct ELE *tree_ptr;
2
3 struct ELE {
4 tree_ptr left;
5 tree_ptr right;
6 long val;
7 };
对于具有如下原型的函数:
long trace(tree_ptr tp);
GCC 产生下面的 x86-64 代码:
1 trace:
; tp in %rdi
2 movl $0, %eax
3 testq %rdi, %rdi
4 je .L3
5 .L5:
6 movq 16(%rdi), %rax
7 movq (%rdi), %rdi
8 testq %rdi, %rdi
9 jne .L5
10 .L3:
11 rep
12 ret
A. 给出一个该函数的 C 版本,使用 while 循环。
B. 用自然语言解释这个函数计算的是什么。
3.70 用家庭作业 3.69 中的树结构,以及一个具有以下原型的函数
long traverse(tree_ptr tp)
GCC 产生下面的 x86-64 代码:
1 traverse:
; tp in %rdi
2 movq %rbx, -24(%rsp)
3 movq %rbp, -16(%rsp)
4 movq %r12, -8(%rsp)
5 subq $24, %rsp
6 movq %rdi, %rbp
7 movabsq $9223372036854775807, %rax
8 test %rdi, %rdi
9 je .L9
10 movq 16(%rdi), %rbx
11 movq (%rdi), %rdi
12 call traverse
13 movq %rax, %r12
14 movq 8(%rbp), %rdi
15 call traverse
16 cmpq %rax, %r12
17 cmovle %r12, %rax
18 cmpq %rbx, %rax
19 cmovg %rbx, %rax
20 .L9:
21 movq (%rsp), %rbx
22 movq 8(%rsp), %rbp
23 movq 16(%rsp), %r12
24 addq $24, %rsp
25 ret
A. 生成这个函数的 C 版本。
B. 用自然语言解释这个函数计算的是什么。
7.6 考虑下面的 swap.c 函数版本,它计算自己被调用的次数:
1 extern int buf[];
2
3 int *bufp0 = &buf[0];
4 static int *bufp1;
5
6 static void incr()
7 {
8 static int count = 0;
9
10 count++;
11 }
12
13 void swap()
14 {
15 int temp;
16
17 incr();
18 bufp1 = &buf[1];
19 temp = *bufp0;
20 *bufp0 = *bufp1;
21 *bufp1 = temp;
22 }
对于每个 swap.o 中定义和引用的符号,请指出它是否在模块 swap.o 的 .symtab 节中有
符号表条目。如果是这样,请指出定义该符号的模块(swap.o 或 main.o)、符号类型(本
地、全局或外部)以及它在模块中所处的节(.text、.data 或 .bss)。
|-------+----------------------+----------+----------------+----|
| 符号 | .swap.o.symtab条目? | 符号类型 | 定义符号的模块 | 节 |
|-------+----------------------+----------+----------------+----|
| buf | | | | |
|-------+----------------------+----------+----------------+----|
| bufp0 | | | | |
|-------+----------------------+----------+----------------+----|
| bufp1 | | | | |
|-------+----------------------+----------+----------------+----|
| swap | | | | |
|-------+----------------------+----------+----------------+----|
| temp | | | | |
|-------+----------------------+----------+----------------+----|
| incr | | | | |
|-------+----------------------+----------+----------------+----|
| count | | | | |
|-------+----------------------+----------+----------------+----|
7.7 不改变任何变量名字,修改 7.6.1 节中的 bar5.c,使得 foo5.c 输出 x 和 y 的正确
值(也就是整数 15213 和 15212 的十六进制表示)。
7.8 在此题中,REF(x,i) --> DEF(x,k) 表示链接器将任意对模块 i 中符号 x 的引用与模
块 k 中符号 x 的定义相关联。在下面每个例子中,用这种符号来说明链接器是如何解
析在每个模块中有多重定义的引用的。如果出现链接时错误(规则 1),写“ERROR”。
如果链接器从定义中任意选择一个(规则 3),那么写“UNKNOWN”。
A. /* Module 1*/ /* Module 2 */
int main() static int main = 1;
{ int p2()
} {
}
a) REF(main.1) --> DEF(____.____)
b) REF(main.2) --> DEF(____.____)
B. /* Module 1 */ /* Module 2 */
int x; double x;
void main() int p2()
{ {
} }
a) REF(x.1) --> DEF(____.____)
b) REF(x.2) --> DEF(____.____)
C. /* Module 1 */ /* Module 2 */
int x = 1; double x = 1.0;
void main() int p2()
{ {
} }
a) REF(x.1) --> DEF(____.____)
b) REF(x.2) --> DEF(____.____)
7.9 考虑下面的程序,它由两个目标模块组成:
1 /* foo6.c */ 1 /* bar6.c */
2 void p2(void); 2 #include <stdio.h>
3 3
4 int main() 4 char main;
5 { 5
6 p2(); 6 void p2()
7 return 0; 7 {
8 } 8 printf("0x%x\n", main);
9 }
当在 Linux 系统中编译和执行这个程序时,即使 p2 不初始化变量 main,它也能打印字符
串“0x55\n”并正常终止。你能解释这一点吗?
7.10 a 和 b 表示当前路径中的目标模块或静态库,而 a->b 表示 a 依赖于 b,也就是说a
引用了一个 b 定义的符号。对于下面的每个场景,给出使得静态链接器能够解析所有
符号引用的最小的命令行(含有最少数量的目标文件和库参数的命令):
A. p.o -> libx.a -> p.o
B. p.o -> libx.a -> liby.a 和 liby.a -> libx.a
C. p.o -> libx.a -> liby.a 和 liby.a -> libx.a -> libz.a
7.11 图 7-12 中的段头部表明数据段占用了存储器中 0x104 个字节。然后,只有开始的
0xe8 字节来自可执行文件的节。引起这种差异的原因是什么?
7.12 图 7-10 中的 swap 程序包含 5 个重定位的引用。对于每个重定位的引用,给出它在
图 7-10 中的行号、运行时存储器地址和值。swap.o 模块中的原始代码和重定位条目
如图7-19 所示。
1 0000000 <swap>:
2 0: 55 push %ebp
3 1: 8b 15 00 00 00 00 mov 0x0,%edx ; Get *bufp0 = &buf[0]
4 3: R_386_32 bufp0 ; Relocation entry
5 7: a1 04 00 00 00 mov 0x4,%eax ; Get buf[1]
6 8: R_386_32 buf ; Relocation entry
7 c: 89 e5 mov %esp, %ebp
8 e: c7 05 00 00 00 00 04 movl $0x4, 0x0 ; bufp1 = &buf[1];
9 15: 00 00 00
10 10: R_386_32 bufp1 ; Relocation entry
11 14: R_386_32 buf ; Relocation entry
12 18: 89 ec mov %ebp, %esp
13 1a: 8b 01 mov (%edx), %ecx ; temp = buf[0];
14 1c: 89 02 mov %eax, (%edx) ; buf[0] = buf[1];
15 1e: a1 00 00 00 00 mov 0x0, %eax ; Get *bufp1 = &buf[1]
16 1f: R_386_32 bufp1 ; Relocation entry
17 23: 89 08 mov %ecx, (%eax) ; buf[1] = temp;
18 25: 5d pop %ebp
19 26: c3 ret
|------------------+------+----|
| 图 7-10 中的符号 | 地址 | 值 |
|------------------+------+----|
| | | |
|------------------+------+----|
| | | |
|------------------+------+----|
| | | |
|------------------+------+----|
| | | |
|------------------+------+----|
| | | |
|------------------+------+----|
图 7-19 家庭作业 7.12 的代买和重定位条目
7.13 考虑图 7-20 中的 C 代码和相应的可重定位目标模块。
A. 确定当模块被重定位时,链接器将修改 .text 中的哪些指令。对于每条这样的指令,
列出它的重定位条目中的信息:节偏移、重定位类型符号名字。
B. 确定当模块被重定位时,链接器将修改 .data 中的哪些数据目标。对于每条这样的
指令,列出它的重定位条目中的信息:节偏移、重定位类型和符号名字。
可以随意使用诸如 objdump 之类的工具来帮助你解答这个题目。
---------------------------------------------------------------------------
1 extern int p3(void);
2 int x = 1;
3 int *xp = &x;
4
5 void p2(int y) {
6 }
7
8 void p1() {
9 p2(*xp + p3());
10 }
---------------------
gitextract_brtqdnlq/
├── .gitignore
├── README
├── bin/
│ ├── d2h
│ └── h2d
├── code/
│ ├── conc/
│ │ ├── badcnt.c
│ │ ├── ctime_ts.c
│ │ ├── echo_cnt.c
│ │ ├── echoserverp.c
│ │ ├── echoservers.c
│ │ ├── echoservert.c
│ │ ├── echoservert_pre.c
│ │ ├── hello.c
│ │ ├── hellobug.c
│ │ ├── norace.c
│ │ ├── psum.c
│ │ ├── race.c
│ │ ├── rand.c
│ │ ├── rand_r.c
│ │ ├── sbuf.c
│ │ ├── sbuf.h
│ │ ├── select.c
│ │ ├── sharing.c
│ │ └── tfgets-main.c
│ ├── data/
│ │ └── show-bytes.c
│ ├── ecf/
│ │ ├── alarm.c
│ │ ├── counterprob.c
│ │ ├── fork.c
│ │ ├── forkprob0.c
│ │ ├── forkprob1.c
│ │ ├── forkprob2.c
│ │ ├── forkprob3.c
│ │ ├── forkprob4.c
│ │ ├── forkprob5.c
│ │ ├── forkprob6.c
│ │ ├── forkprob7.c
│ │ ├── forkprob8.c
│ │ ├── hello-asm.sa
│ │ ├── kill.c
│ │ ├── procmask1.c
│ │ ├── procmask2.c
│ │ ├── restart.c
│ │ ├── rfork.c
│ │ ├── setjmp.c
│ │ ├── shellex.c
│ │ ├── sigint1.c
│ │ ├── signal1.c
│ │ ├── signal2.c
│ │ ├── signal3.c
│ │ ├── signal4.c
│ │ ├── signalprob0.c
│ │ ├── waitpid1.c
│ │ ├── waitpid2.c
│ │ ├── waitprob0.c
│ │ ├── waitprob1.c
│ │ └── waitprob3.c
│ ├── include/
│ │ └── csapp.h
│ ├── intro/
│ │ └── hello.c
│ ├── io/
│ │ ├── cpfile.c
│ │ ├── cpstdin.c
│ │ └── statcheck.c
│ ├── link/
│ │ ├── addvec.c
│ │ ├── dll.c
│ │ ├── elfstructs.c
│ │ ├── main.c
│ │ ├── main2.c
│ │ ├── multvec.c
│ │ ├── p-exe.d
│ │ ├── pdata-exe.d
│ │ └── swap.c
│ ├── mem/
│ │ ├── matmult/
│ │ │ └── mm.c
│ │ └── mountain/
│ │ └── mountain.c
│ ├── netp/
│ │ ├── echo.c
│ │ ├── echoclient.c
│ │ ├── echoserveri.c
│ │ ├── hostinfo.c
│ │ └── tiny/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ └── tiny.c
│ ├── src/
│ │ └── csapp.c
│ └── vm/
│ ├── malloc/
│ │ ├── memlib.c
│ │ └── mm.c
│ ├── memlib.h
│ └── mm.h
├── common/
│ ├── csapp.c
│ └── csapp.h
├── exercise/
│ ├── 00-topic.txt
│ ├── README
│ ├── ex10-10.c
│ ├── ex10-2.c
│ ├── ex10-3.c
│ ├── ex10-5.c
│ ├── ex10-6.c
│ ├── ex10-7.c
│ ├── ex10-8.c
│ ├── ex10-9.txt
│ ├── ex11-10/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-11/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-12/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-13/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-2.c
│ ├── ex11-3.c
│ ├── ex11-6/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-7/
│ │ ├── Sequence.mpg
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-8/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex11-9/
│ │ ├── cgi-bin/
│ │ │ └── adder.c
│ │ ├── home.html
│ │ └── tiny.c
│ ├── ex12-22.c
│ ├── ex2-36.c
│ ├── ex2-42.c
│ ├── ex2-58.c
│ ├── ex2-59.c
│ ├── ex2-60.c
│ ├── ex2-61.c
│ ├── ex2-62.c
│ ├── ex2-63.c
│ ├── ex2-64.c
│ ├── ex2-65.c
│ ├── ex2-66.c
│ ├── ex2-67.c
│ ├── ex2-68.c
│ ├── ex2-69.c
│ ├── ex2-7.c
│ ├── ex2-70.c
│ ├── ex2-71.c
│ ├── ex2-72.c
│ ├── ex2-73.c
│ ├── ex2-74.c
│ ├── ex2-75.c
│ ├── ex2-76.c
│ ├── ex2-77.c
│ ├── ex2-78.c
│ ├── ex2-79.c
│ ├── ex2-80.c
│ ├── ex2-81.c
│ ├── ex2-82.txt
│ ├── ex2-83.c
│ ├── ex2-84.txt
│ ├── ex2-85.txt
│ ├── ex2-86.txt
│ ├── ex2-87.txt
│ ├── ex2-88.txt
│ ├── ex2-89.c
│ ├── ex2-90.txt
│ ├── ex2-91.c
│ ├── ex2-92.c
│ ├── ex2-93.c
│ ├── ex2-94.c
│ ├── ex2-95.c
│ ├── ex2-96.c
│ ├── ex3-19.c
│ ├── ex3-34.c
│ ├── ex3-54.c
│ ├── ex3-55.asm
│ ├── ex3-56.txt
│ ├── ex3-57.c
│ ├── ex3-58.c
│ ├── ex3-59.c
│ ├── ex3-60.txt
│ ├── ex3-61.c
│ ├── ex3-62.c
│ ├── ex3-63.txt
│ ├── ex3-64.txt
│ ├── ex3-65.txt
│ ├── ex3-66.txt
│ ├── ex3-67.c
│ ├── ex3-68.c
│ ├── ex3-69.c
│ ├── ex3-70.c
│ ├── ex7-10.txt
│ ├── ex7-11.txt
│ ├── ex7-12.txt
│ ├── ex7-13.txt
│ ├── ex7-14.txt
│ ├── ex7-15.txt
│ ├── ex7-6.txt
│ ├── ex7-7.c
│ ├── ex7-8.txt
│ ├── ex7-9.txt
│ ├── ex8-10.txt
│ ├── ex8-11.c
│ ├── ex8-12.c
│ ├── ex8-13.c
│ ├── ex8-14.c
│ ├── ex8-15.c
│ ├── ex8-16.c
│ ├── ex8-17.txt
│ ├── ex8-18.c
│ ├── ex8-19.txt
│ ├── ex8-2.c
│ ├── ex8-20.c
│ ├── ex8-21.c
│ ├── ex8-22.c
│ ├── ex8-23.txt
│ ├── ex8-24.c
│ ├── ex8-25.c
│ ├── ex8-26/
│ │ ├── Makefile
│ │ ├── job.c
│ │ ├── job.h
│ │ ├── random_fork.c
│ │ ├── shellex.c
│ │ └── t-job.c
│ ├── ex8-3.c
│ ├── ex8-4.c
│ ├── ex8-5.c
│ ├── ex8-6.c
│ ├── ex8-7.c
│ ├── ex8-8.c
│ ├── ex8-9.txt
│ ├── ex9-14.c
│ ├── ex9-17.c
│ ├── ex9-18.c
│ ├── ex9-20/
│ │ ├── Makefile
│ │ ├── ex9-20.c
│ │ ├── t-block-operate.c
│ │ ├── t-block-quick-sort.c
│ │ ├── t-malloc.c
│ │ ├── t2.c
│ │ ├── t3.c
│ │ └── t9-20.c
│ ├── ex9-5.c
│ ├── ex9-8.c
│ ├── ex9-9.c
│ ├── t2-59.c
│ ├── t2-95.c
│ ├── t2-96.c
│ ├── t3-68.sh
│ ├── t8-22.c
│ ├── t8-25.c
│ ├── t9-14.c
│ ├── t9-14.sh
│ └── t9-17.c
├── hard-task.txt
├── missing.c
├── notes/
│ ├── .gitignore
│ ├── api.txt
│ ├── ch03.txt
│ ├── ch07.txt
│ ├── ch08.txt
│ ├── ch09.txt
│ └── ch11.txt
└── sample/
├── .gitignore
├── ch02/
│ ├── .gitignore
│ └── show-bytes.c
├── ch03/
│ ├── buf-overflow.c
│ ├── code.c
│ ├── main.c
│ ├── simple.c
│ └── simple_1.c
├── ch07/
│ ├── .gitignore
│ ├── addvec.c
│ ├── bar1.c
│ ├── bar2.c
│ ├── bar3.c
│ ├── bar4.c
│ ├── bar5.c
│ ├── dll.c
│ ├── foo1.c
│ ├── foo2.c
│ ├── foo3.c
│ ├── foo4.c
│ ├── foo5.c
│ ├── linkerror.c
│ ├── main.c
│ ├── main2.c
│ ├── multvec.c
│ ├── swap.c
│ └── vector.h
├── ch08/
│ ├── .gitignore
│ ├── alarm.c
│ ├── fork.c
│ ├── hello-asm.sa
│ ├── kill.c
│ ├── procmask1.c
│ ├── procmask2.c
│ ├── restart.c
│ ├── rfork.c
│ ├── setjmp.c
│ ├── shellex.c
│ ├── sigint1.c
│ ├── signal1.c
│ ├── signal2.c
│ ├── signal3.c
│ ├── signal4.c
│ ├── waitpid1.c
│ └── waitpid2.c
├── ch09/
│ ├── .gitignore
│ ├── memlib.c
│ ├── mm-test.c
│ └── mm.c
├── ch10/
│ ├── .gitignore
│ ├── cpfile.c
│ ├── cpstdin.c
│ └── statcheck.c
├── ch11/
│ ├── echo.c
│ ├── echoclient.c
│ ├── echoserveri.c
│ ├── hostinfo.c
│ └── tiny/
│ ├── cgi-bin/
│ │ └── adder.c
│ ├── home.html
│ ├── rfc2616.txt
│ └── tiny.c
└── ch12/
├── Makefile
├── badcnt.c
├── echo_cnt.c
├── echoserverp.c
├── echoservers.c
├── echoservert.c
├── echoservert_pre.c
├── goodcnt.c
├── hello.c
├── sbuf.c
├── sbuf.h
├── select.c
└── sharing.c
SYMBOL INDEX (723 symbols across 257 files)
FILE: code/conc/badcnt.c
function main (line 12) | int main(int argc, char **argv)
FILE: code/conc/ctime_ts.c
function init_ctime_ts (line 9) | static void init_ctime_ts(void)
function main (line 27) | int main()
FILE: code/conc/echo_cnt.c
function init_echo_cnt (line 11) | static void init_echo_cnt(void)
function echo_cnt (line 17) | void echo_cnt(int connfd)
FILE: code/conc/echoserverp.c
function sigchld_handler (line 8) | void sigchld_handler(int sig) //line:conc:echoserverp:handlerstart
function main (line 15) | int main(int argc, char **argv)
FILE: code/conc/echoservers.c
type pool (line 7) | typedef struct { /* represents a pool of connected descriptors */ //line...
function main (line 24) | int main(int argc, char **argv)
function init_pool (line 57) | void init_pool(int listenfd, pool *p)
function add_client (line 73) | void add_client(int connfd, pool *p)
function check_clients (line 99) | void check_clients(pool *p)
FILE: code/conc/echoservert.c
function main (line 10) | int main(int argc, char **argv)
FILE: code/conc/echoservert_pre.c
function main (line 15) | int main(int argc, char **argv)
FILE: code/conc/hello.c
function main (line 8) | int main() //line:conc:hello:main
FILE: code/conc/hellobug.c
function main (line 8) | int main()
FILE: code/conc/norace.c
function main (line 10) | int main()
FILE: code/conc/psum.c
function main (line 14) | int main(int argc, char **argv)
FILE: code/conc/race.c
function main (line 10) | int main()
FILE: code/conc/rand.c
function rand (line 8) | int rand(void)
function srand (line 15) | void srand(unsigned int seed)
function main (line 21) | int main()
FILE: code/conc/rand_r.c
function rand_r (line 6) | int rand_r(unsigned int *nextp)
function main (line 13) | int main()
FILE: code/conc/sbuf.c
function sbuf_init (line 7) | void sbuf_init(sbuf_t *sp, int n)
function sbuf_deinit (line 20) | void sbuf_deinit(sbuf_t *sp)
function sbuf_insert (line 28) | void sbuf_insert(sbuf_t *sp, int item)
function sbuf_remove (line 40) | int sbuf_remove(sbuf_t *sp)
FILE: code/conc/sbuf.h
type sbuf_t (line 7) | typedef struct {
FILE: code/conc/select.c
function main (line 6) | int main(int argc, char **argv)
function command (line 37) | void command(void) {
FILE: code/conc/sharing.c
function main (line 8) | int main()
FILE: code/conc/tfgets-main.c
function main (line 6) | int main()
FILE: code/data/show-bytes.c
function show_bytes (line 10) | void show_bytes(byte_pointer start, int len) {
function show_int (line 17) | void show_int(int x) {
function show_float (line 21) | void show_float(float x) {
function show_pointer (line 25) | void show_pointer(void *x) {
function test_show_bytes (line 32) | void test_show_bytes(int val) {
function simple_show_a (line 42) | void simple_show_a() {
function simple_show_b (line 52) | void simple_show_b() {
function float_eg (line 62) | void float_eg() {
function string_ueg (line 77) | void string_ueg() {
function string_leg (line 84) | void string_leg() {
function show_twocomp (line 91) | void show_twocomp()
function main (line 102) | int main(int argc, char *argv[])
FILE: code/ecf/alarm.c
function handler (line 4) | void handler(int sig)
function main (line 17) | int main()
FILE: code/ecf/counterprob.c
function handler (line 6) | void handler(int sig)
function main (line 13) | int main()
FILE: code/ecf/fork.c
function main (line 4) | int main()
FILE: code/ecf/forkprob0.c
function main (line 4) | int main()
FILE: code/ecf/forkprob1.c
function main (line 4) | int main()
FILE: code/ecf/forkprob2.c
function end (line 4) | void end(void)
function main (line 9) | int main()
FILE: code/ecf/forkprob3.c
function main (line 4) | int main()
FILE: code/ecf/forkprob4.c
function doit (line 4) | void doit()
function main (line 12) | int main()
FILE: code/ecf/forkprob5.c
function doit (line 4) | void doit()
function main (line 14) | int main()
FILE: code/ecf/forkprob6.c
function doit (line 4) | void doit()
function main (line 14) | int main()
FILE: code/ecf/forkprob7.c
function main (line 5) | int main()
FILE: code/ecf/forkprob8.c
function foo (line 4) | void foo(int n)
function main (line 15) | int main(int argc, char **argv)
FILE: code/ecf/kill.c
function main (line 4) | int main()
FILE: code/ecf/procmask1.c
function initjobs (line 3) | void initjobs()
function addjob (line 7) | void addjob(int pid)
function deletejob (line 11) | void deletejob(int pid)
function handler (line 16) | void handler(int sig)
function main (line 25) | int main(int argc, char **argv)
FILE: code/ecf/procmask2.c
function initjobs (line 3) | void initjobs()
function addjob (line 7) | void addjob(int pid)
function deletejob (line 11) | void deletejob(int pid)
function handler (line 16) | void handler(int sig)
function main (line 25) | int main(int argc, char **argv)
FILE: code/ecf/restart.c
function handler (line 6) | void handler(int sig)
function main (line 11) | int main()
FILE: code/ecf/rfork.c
function pid_t (line 18) | pid_t Fork(void)
FILE: code/ecf/setjmp.c
function main (line 11) | int main()
function foo (line 28) | void foo(void)
function bar (line 35) | void bar(void)
FILE: code/ecf/shellex.c
function main (line 10) | int main()
function eval (line 29) | void eval(char *cmdline)
function builtin_command (line 62) | int builtin_command(char **argv)
function parseline (line 74) | int parseline(char *buf, char **argv)
FILE: code/ecf/sigint1.c
function handler (line 4) | void handler(int sig) /* SIGINT handler */ //line:ecf:sigint1:beginhan...
function main (line 10) | int main()
FILE: code/ecf/signal1.c
function handler1 (line 4) | void handler1(int sig)
function main (line 15) | int main()
FILE: code/ecf/signal2.c
function handler2 (line 4) | void handler2(int sig)
function main (line 16) | int main()
FILE: code/ecf/signal3.c
function handler2 (line 4) | void handler2(int sig)
function main (line 16) | int main() {
FILE: code/ecf/signal4.c
function handler2 (line 4) | void handler2(int sig)
function main (line 16) | int main()
FILE: code/ecf/signalprob0.c
function handler1 (line 11) | void handler1(int sig) {
function main (line 18) | int main() {
FILE: code/ecf/waitpid1.c
function main (line 5) | int main()
FILE: code/ecf/waitpid2.c
function main (line 5) | int main()
FILE: code/ecf/waitprob0.c
function main (line 4) | int main()
FILE: code/ecf/waitprob1.c
function main (line 4) | int main()
FILE: code/ecf/waitprob3.c
function main (line 4) | int main()
FILE: code/include/csapp.h
type SA (line 36) | typedef struct sockaddr SA;
type rio_t (line 42) | typedef struct {
type timeval (line 94) | struct timeval
type stat (line 96) | struct stat
type stat (line 97) | struct stat
type sockaddr (line 121) | struct sockaddr
type sockaddr (line 123) | struct sockaddr
type sockaddr (line 124) | struct sockaddr
type hostent (line 127) | struct hostent
type hostent (line 128) | struct hostent
FILE: code/intro/hello.c
function main (line 4) | int main()
FILE: code/io/cpfile.c
function main (line 4) | int main(int argc, char **argv)
FILE: code/io/cpstdin.c
function main (line 4) | int main(void)
FILE: code/io/statcheck.c
function main (line 4) | int main (int argc, char **argv)
FILE: code/link/addvec.c
function addvec (line 3) | void addvec(int *x, int *y,
FILE: code/link/dll.c
function main (line 10) | int main()
FILE: code/link/elfstructs.c
type Elf_Symbol (line 2) | typedef struct {
type Elf32_Rel (line 15) | typedef struct {
FILE: code/link/main.c
function main (line 7) | int main()
FILE: code/link/main2.c
function main (line 10) | int main()
FILE: code/link/multvec.c
function multvec (line 3) | void multvec(int *x, int *y,
FILE: code/link/swap.c
function swap (line 8) | void swap()
FILE: code/mem/matmult/mm.c
function checkresult (line 15) | void checkresult(array c, int n)
function run (line 30) | double run(test_funct f, int n)
function reset (line 40) | void reset(array c, int n)
function init (line 52) | void init(array a, array b, int n)
function printarray (line 66) | void printarray(array a, int n)
function ijk (line 81) | void ijk(array A, array B, array C, int n)
function jik (line 98) | void jik(array A, array B, array C, int n)
function ikj (line 114) | void ikj(array A, array B, array C, int n)
function kij (line 129) | void kij(array A, array B, array C, int n)
function kji (line 144) | void kji(array A, array B, array C, int n)
function jki (line 159) | void jki(array A, array B, array C, int n)
function main (line 179) | int main()
FILE: code/mem/mountain/mountain.c
function main (line 23) | int main()
function init_data (line 62) | void init_data(double *data, int n)
function test (line 75) | void test(int elems, int stride) /* The test function */
function run (line 92) | double run(int size, int stride, double Mhz)
FILE: code/netp/echo.c
function echo (line 7) | void echo(int connfd)
FILE: code/netp/echoclient.c
function main (line 7) | int main(int argc, char **argv)
FILE: code/netp/echoserveri.c
function main (line 9) | int main(int argc, char **argv)
FILE: code/netp/hostinfo.c
function main (line 4) | int main(int argc, char **argv)
FILE: code/netp/tiny/cgi-bin/adder.c
function main (line 7) | int main(void) {
FILE: code/netp/tiny/tiny.c
function main (line 17) | int main(int argc, char **argv)
function doit (line 43) | void doit(int fd)
function read_requesthdrs (line 93) | void read_requesthdrs(rio_t *rp)
function parse_uri (line 111) | int parse_uri(char *uri, char *filename, char *cgiargs)
function serve_static (line 142) | void serve_static(int fd, char *filename, int filesize)
function get_filetype (line 166) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 183) | void serve_dynamic(int fd, char *filename, char *cgiargs)
function clienterror (line 207) | void clienterror(int fd, char *cause, char *errnum,
FILE: code/src/csapp.c
function unix_error (line 9) | void unix_error(char *msg) /* unix-style error */
function posix_error (line 16) | void posix_error(int code, char *msg) /* posix-style error */
function dns_error (line 22) | void dns_error(char *msg) /* dns-style error */
function app_error (line 28) | void app_error(char *msg) /* application error */
function pid_t (line 40) | pid_t Fork(void)
function Execve (line 50) | void Execve(const char *filename, char *const argv[], char *const envp[])
function pid_t (line 57) | pid_t Wait(int *status)
function pid_t (line 67) | pid_t Waitpid(pid_t pid, int *iptr, int options)
function Kill (line 77) | void Kill(pid_t pid, int signum)
function Pause (line 86) | void Pause()
function Sleep (line 92) | unsigned int Sleep(unsigned int secs)
function Alarm (line 101) | unsigned int Alarm(unsigned int seconds) {
function Setpgid (line 105) | void Setpgid(pid_t pid, pid_t pgid) {
function pid_t (line 113) | pid_t Getpgrp(void) {
function handler_t (line 122) | handler_t *Signal(int signum, handler_t *handler)
function Sigprocmask (line 136) | void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
function Sigemptyset (line 143) | void Sigemptyset(sigset_t *set)
function Sigfillset (line 150) | void Sigfillset(sigset_t *set)
function Sigaddset (line 157) | void Sigaddset(sigset_t *set, int signum)
function Sigdelset (line 164) | void Sigdelset(sigset_t *set, int signum)
function Sigismember (line 171) | int Sigismember(const sigset_t *set, int signum)
function Open (line 184) | int Open(const char *pathname, int flags, mode_t mode)
function Read (line 193) | ssize_t Read(int fd, void *buf, size_t count)
function Write (line 202) | ssize_t Write(int fd, const void *buf, size_t count)
function off_t (line 211) | off_t Lseek(int fildes, off_t offset, int whence)
function Close (line 220) | void Close(int fd)
function Select (line 228) | int Select(int n, fd_set *readfds, fd_set *writefds,
function Dup2 (line 238) | int Dup2(int fd1, int fd2)
function Stat (line 247) | void Stat(const char *filename, struct stat *buf)
function Fstat (line 253) | void Fstat(int fd, struct stat *buf)
function Munmap (line 271) | void Munmap(void *start, size_t length)
function Free (line 308) | void Free(void *ptr)
function Fclose (line 316) | void Fclose(FILE *fp)
function FILE (line 322) | FILE *Fdopen(int fd, const char *type)
function FILE (line 342) | FILE *Fopen(const char *filename, const char *mode)
function Fputs (line 352) | void Fputs(const char *ptr, FILE *stream)
function Fread (line 358) | size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
function Fwrite (line 367) | void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
function Socket (line 378) | int Socket(int domain, int type, int protocol)
function Setsockopt (line 387) | void Setsockopt(int s, int level, int optname, const void *optval, int o...
function Bind (line 395) | void Bind(int sockfd, struct sockaddr *my_addr, int addrlen)
function Listen (line 403) | void Listen(int s, int backlog)
function Accept (line 411) | int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
function Connect (line 420) | void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
type hostent (line 433) | struct hostent
type hostent (line 435) | struct hostent
type hostent (line 443) | struct hostent
type hostent (line 445) | struct hostent
function Pthread_create (line 456) | void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
function Pthread_cancel (line 465) | void Pthread_cancel(pthread_t tid) {
function Pthread_join (line 472) | void Pthread_join(pthread_t tid, void **thread_return) {
function Pthread_detach (line 480) | void Pthread_detach(pthread_t tid) {
function Pthread_exit (line 488) | void Pthread_exit(void *retval) {
function pthread_t (line 492) | pthread_t Pthread_self(void) {
function Pthread_once (line 496) | void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
function Sem_init (line 504) | void Sem_init(sem_t *sem, int pshared, unsigned int value)
function P (line 510) | void P(sem_t *sem)
function V (line 516) | void V(sem_t *sem)
function rio_readn (line 529) | ssize_t rio_readn(int fd, void *usrbuf, size_t n)
function rio_writen (line 555) | ssize_t rio_writen(int fd, void *usrbuf, size_t n)
function rio_read (line 585) | static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
function rio_readinitb (line 617) | void rio_readinitb(rio_t *rp, int fd)
function rio_readnb (line 629) | ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
function rio_readlineb (line 655) | ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
function Rio_readn (line 681) | ssize_t Rio_readn(int fd, void *ptr, size_t nbytes)
function Rio_writen (line 690) | void Rio_writen(int fd, void *usrbuf, size_t n)
function Rio_readinitb (line 696) | void Rio_readinitb(rio_t *rp, int fd)
function Rio_readnb (line 701) | ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n)
function Rio_readlineb (line 710) | ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
function open_clientfd (line 729) | int open_clientfd(char *hostname, int port)
function open_listenfd (line 759) | int open_listenfd(int port)
function Open_clientfd (line 792) | int Open_clientfd(char *hostname, int port)
function Open_listenfd (line 805) | int Open_listenfd(int port)
FILE: code/vm/malloc/memlib.c
function mem_init (line 28) | void mem_init(void)
function mem_deinit (line 57) | void mem_deinit(void)
function mem_reset_brk (line 64) | void mem_reset_brk()
function mem_heapsize (line 88) | size_t mem_heapsize()
function mem_pagesize (line 96) | size_t mem_pagesize()
FILE: code/vm/malloc/mm.c
function mm_init (line 66) | int mm_init(void)
function mm_free (line 134) | void mm_free(void *bp)
function mm_checkheap (line 240) | void mm_checkheap(int verbose)
function place (line 278) | static void place(void *bp, size_t asize)
function printblock (line 337) | static void printblock(void *bp)
function checkblock (line 357) | static void checkblock(void *bp)
function checkheap (line 368) | void checkheap(int verbose)
FILE: code/vm/mm.h
type team_t (line 11) | typedef struct {
FILE: common/csapp.c
function unix_error (line 9) | void unix_error(char *msg) /* unix-style error */
function posix_error (line 16) | void posix_error(int code, char *msg) /* posix-style error */
function dns_error (line 22) | void dns_error(char *msg) /* dns-style error */
function app_error (line 28) | void app_error(char *msg) /* application error */
function pid_t (line 40) | pid_t Fork(void)
function Execve (line 50) | void Execve(const char *filename, char *const argv[], char *const envp[])
function pid_t (line 57) | pid_t Wait(int *status)
function pid_t (line 67) | pid_t Waitpid(pid_t pid, int *iptr, int options)
function Kill (line 77) | void Kill(pid_t pid, int signum)
function Pause (line 86) | void Pause()
function Sleep (line 92) | unsigned int Sleep(unsigned int secs)
function Alarm (line 101) | unsigned int Alarm(unsigned int seconds) {
function Setpgid (line 105) | void Setpgid(pid_t pid, pid_t pgid) {
function pid_t (line 113) | pid_t Getpgrp(void) {
function handler_t (line 122) | handler_t *Signal(int signum, handler_t *handler)
function Sigprocmask (line 136) | void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
function Sigemptyset (line 143) | void Sigemptyset(sigset_t *set)
function Sigfillset (line 150) | void Sigfillset(sigset_t *set)
function Sigaddset (line 157) | void Sigaddset(sigset_t *set, int signum)
function Sigdelset (line 164) | void Sigdelset(sigset_t *set, int signum)
function Sigismember (line 171) | int Sigismember(const sigset_t *set, int signum)
function Open (line 184) | int Open(const char *pathname, int flags, mode_t mode)
function Read (line 193) | ssize_t Read(int fd, void *buf, size_t count)
function Write (line 202) | ssize_t Write(int fd, const void *buf, size_t count)
function off_t (line 211) | off_t Lseek(int fildes, off_t offset, int whence)
function Close (line 220) | void Close(int fd)
function Select (line 228) | int Select(int n, fd_set *readfds, fd_set *writefds,
function Dup2 (line 238) | int Dup2(int fd1, int fd2)
function Stat (line 247) | void Stat(const char *filename, struct stat *buf)
function Fstat (line 253) | void Fstat(int fd, struct stat *buf)
function Munmap (line 271) | void Munmap(void *start, size_t length)
function Free (line 308) | void Free(void *ptr)
function Fclose (line 316) | void Fclose(FILE *fp)
function FILE (line 322) | FILE *Fdopen(int fd, const char *type)
function FILE (line 342) | FILE *Fopen(const char *filename, const char *mode)
function Fputs (line 352) | void Fputs(const char *ptr, FILE *stream)
function Fread (line 358) | size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
function Fwrite (line 367) | void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
function Socket (line 378) | int Socket(int domain, int type, int protocol)
function Setsockopt (line 387) | void Setsockopt(int s, int level, int optname, const void *optval, int o...
function Bind (line 395) | void Bind(int sockfd, struct sockaddr *my_addr, int addrlen)
function Listen (line 403) | void Listen(int s, int backlog)
function Accept (line 411) | int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
function Connect (line 420) | void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
type hostent (line 433) | struct hostent
type hostent (line 435) | struct hostent
type hostent (line 443) | struct hostent
type hostent (line 445) | struct hostent
function Pthread_create (line 456) | void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
function Pthread_cancel (line 465) | void Pthread_cancel(pthread_t tid) {
function Pthread_join (line 472) | void Pthread_join(pthread_t tid, void **thread_return) {
function Pthread_detach (line 480) | void Pthread_detach(pthread_t tid) {
function Pthread_exit (line 488) | void Pthread_exit(void *retval) {
function pthread_t (line 492) | pthread_t Pthread_self(void) {
function Pthread_once (line 496) | void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
function Sem_init (line 504) | void Sem_init(sem_t *sem, int pshared, unsigned int value)
function P (line 510) | void P(sem_t *sem)
function V (line 516) | void V(sem_t *sem)
function rio_readn (line 529) | ssize_t rio_readn(int fd, void *usrbuf, size_t n)
function rio_writen (line 555) | ssize_t rio_writen(int fd, void *usrbuf, size_t n)
function rio_read (line 585) | static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
function rio_readinitb (line 617) | void rio_readinitb(rio_t *rp, int fd)
function rio_readnb (line 629) | ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
function rio_readlineb (line 655) | ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
function Rio_readn (line 681) | ssize_t Rio_readn(int fd, void *ptr, size_t nbytes)
function Rio_writen (line 690) | void Rio_writen(int fd, void *usrbuf, size_t n)
function Rio_readinitb (line 696) | void Rio_readinitb(rio_t *rp, int fd)
function Rio_readnb (line 701) | ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n)
function Rio_readlineb (line 710) | ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
function open_clientfd (line 729) | int open_clientfd(char *hostname, int port)
function open_listenfd (line 759) | int open_listenfd(int port)
function Open_clientfd (line 792) | int Open_clientfd(char *hostname, int port)
function Open_listenfd (line 805) | int Open_listenfd(int port)
FILE: common/csapp.h
type SA (line 36) | typedef struct sockaddr SA;
type rio_t (line 42) | typedef struct {
type timeval (line 94) | struct timeval
type stat (line 96) | struct stat
type stat (line 97) | struct stat
type sockaddr (line 121) | struct sockaddr
type sockaddr (line 123) | struct sockaddr
type sockaddr (line 124) | struct sockaddr
type hostent (line 127) | struct hostent
type hostent (line 128) | struct hostent
FILE: exercise/ex10-10.c
function main (line 14) | int main(int argc, char **argv)
FILE: exercise/ex10-2.c
function main (line 15) | int main()
FILE: exercise/ex10-3.c
function main (line 13) | int main()
FILE: exercise/ex10-5.c
function main (line 15) | int main()
FILE: exercise/ex10-6.c
function main (line 15) | int main(void)
FILE: exercise/ex10-7.c
function main (line 19) | int main(int argc, char **argv)
FILE: exercise/ex10-8.c
function main (line 20) | int main(int argc, char **argv)
FILE: exercise/ex11-10/cgi-bin/adder.c
function main (line 12) | int main(void)
FILE: exercise/ex11-10/tiny.c
function reap_child (line 22) | void reap_child(int signo)
function main (line 38) | int main(int argc, char **argv)
function doit (line 73) | void doit(int fd)
function clienterror (line 150) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 172) | int parse_uri(char *uri, char *filename, char *cgiargs)
function serve_static (line 197) | void serve_static(int fd, char *filename, int filesize)
function get_filetype (line 253) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 265) | void serve_dynamic(int fd, char *filename, char *cgiargs)
FILE: exercise/ex11-11/cgi-bin/adder.c
function main (line 12) | int main(void)
FILE: exercise/ex11-11/tiny.c
function reap_child (line 22) | void reap_child(int signo)
function main (line 38) | int main(int argc, char **argv)
function write_to_file (line 106) | void write_to_file(char *request)
function doit (line 121) | void doit(int fd)
function clienterror (line 161) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 183) | int parse_uri(char *uri, char *filename, char *cgiargs)
function send_response_body (line 208) | void send_response_body(int fd, char *filename)
function serve_static (line 251) | void serve_static(int fd, char *filename, int filesize, char *method)
function get_filetype (line 271) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 285) | void serve_dynamic(int fd, char *filename, char *cgiargs, char *method)
FILE: exercise/ex11-12/cgi-bin/adder.c
function main (line 12) | int main(void)
FILE: exercise/ex11-12/tiny.c
function reap_child (line 22) | void reap_child(int signo)
function main (line 38) | int main(int argc, char **argv)
function write_to_file (line 106) | void write_to_file(char *request)
function get_post_entity (line 122) | void get_post_entity(char *request, char *entity, int len)
function doit (line 149) | void doit(int fd)
function clienterror (line 194) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 216) | int parse_uri(char *uri, char *filename, char *cgiargs)
function send_response_body (line 241) | void send_response_body(int fd, char *filename)
function serve_static (line 284) | void serve_static(int fd, char *filename, int filesize, char *method)
function get_filetype (line 304) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 318) | void serve_dynamic(int fd, char *filename, char *cgiargs, char *method)
FILE: exercise/ex11-13/cgi-bin/adder.c
function main (line 12) | int main(void)
FILE: exercise/ex11-13/tiny.c
function reap_child (line 36) | void reap_child(int signo)
function client_offline (line 51) | void client_offline(int signo, siginfo_t *info, void *context)
function main (line 66) | int main(int argc, char **argv)
function write_to_file (line 155) | void write_to_file(char *request)
function get_post_entity (line 171) | void get_post_entity(char *request, char *entity, int len)
function doit (line 198) | void doit(int fd)
function clienterror (line 243) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 265) | int parse_uri(char *uri, char *filename, char *cgiargs)
function send_response_body (line 290) | void send_response_body(int fd, char *filename)
function serve_static (line 333) | void serve_static(int fd, char *filename, int filesize, char *method)
function get_filetype (line 353) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 367) | void serve_dynamic(int fd, char *filename, char *cgiargs, char *method)
FILE: exercise/ex11-2.c
function main (line 24) | int main(int argc, char *argv[])
FILE: exercise/ex11-3.c
function main (line 20) | int main(int argc, char *argv[])
FILE: exercise/ex11-6/cgi-bin/adder.c
function main (line 9) | int main(void)
FILE: exercise/ex11-6/tiny.c
function main (line 20) | int main(int argc, char **argv)
function doit (line 42) | void doit(int fd)
function clienterror (line 119) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 141) | int parse_uri(char *uri, char *filename, char *cgiargs)
function serve_static (line 167) | void serve_static(int fd, char *filename, int filesize)
function get_filetype (line 191) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 203) | void serve_dynamic(int fd, char *filename, char *cgiargs)
FILE: exercise/ex11-7/cgi-bin/adder.c
function main (line 12) | int main(void)
FILE: exercise/ex11-7/tiny.c
function reap_child (line 22) | void reap_child(int signo)
function main (line 38) | int main(int argc, char **argv)
function doit (line 73) | void doit(int fd)
function clienterror (line 150) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 172) | int parse_uri(char *uri, char *filename, char *cgiargs)
function serve_static (line 197) | void serve_static(int fd, char *filename, int filesize)
function get_filetype (line 253) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 267) | void serve_dynamic(int fd, char *filename, char *cgiargs)
FILE: exercise/ex11-8/cgi-bin/adder.c
function main (line 9) | int main(void)
FILE: exercise/ex11-8/tiny.c
function reap_child (line 28) | void reap_child(int signo)
function main (line 44) | int main(int argc, char **argv)
function doit (line 79) | void doit(int fd)
function clienterror (line 156) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 178) | int parse_uri(char *uri, char *filename, char *cgiargs)
function serve_static (line 204) | void serve_static(int fd, char *filename, int filesize)
function get_filetype (line 228) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 240) | void serve_dynamic(int fd, char *filename, char *cgiargs)
FILE: exercise/ex11-9/cgi-bin/adder.c
function main (line 9) | int main(void)
FILE: exercise/ex11-9/tiny.c
function reap_child (line 33) | void reap_child(int signo)
function main (line 49) | int main(int argc, char **argv)
function doit (line 84) | void doit(int fd)
function clienterror (line 161) | void clienterror(int fd, char *cause, char *errnum,
function parse_uri (line 183) | int parse_uri(char *uri, char *filename, char *cgiargs)
function serve_static (line 209) | void serve_static(int fd, char *filename, int filesize)
function get_filetype (line 265) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 277) | void serve_dynamic(int fd, char *filename, char *cgiargs)
FILE: exercise/ex12-22.c
function echo (line 27) | void echo(int connfd)
function command (line 45) | void command(void)
function open_listenfd (line 62) | int open_listenfd(int port)
function Open_listenfd (line 92) | int Open_listenfd(int port)
function Select (line 103) | int Select(int n, fd_set *readfds, fd_set *writefds,
function Accept (line 115) | int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
function Close (line 126) | void Close(int fd)
function main (line 135) | int main(int argc, char **argv)
FILE: exercise/ex2-36.c
function tmult_ok (line 13) | int tmult_ok(int x, int y)
function book_tmult_ok (line 21) | int book_tmult_ok(int x, int y)
FILE: exercise/ex2-42.c
function div16 (line 12) | int div16(int x)
function book_div16 (line 25) | int book_div16(int x)
FILE: exercise/ex2-58.c
function is_little_endian (line 7) | int is_little_endian(void)
FILE: exercise/ex2-59.c
function combine_word (line 7) | int combine_word(unsigned x, unsigned y)
FILE: exercise/ex2-60.c
function replace_byte (line 15) | unsigned replace_byte(unsigned x, unsigned char b, int i)
FILE: exercise/ex2-61.c
function ex2_61 (line 24) | void ex2_61(void)
FILE: exercise/ex2-62.c
function int_shifts_are_logical (line 11) | int int_shifts_are_logical(void)
FILE: exercise/ex2-63.c
function sra (line 12) | int sra(int x, int k)
function srl (line 29) | unsigned srl(unsigned x, int k)
FILE: exercise/ex2-64.c
function any_even_one (line 11) | int any_even_one(unsigned x)
FILE: exercise/ex2-65.c
function even_ones (line 28) | int even_ones(unsigned x)
FILE: exercise/ex2-66.c
function leftmost_one (line 15) | int leftmost_one(unsigned x)
function rightmost_one (line 33) | int rightmost_one(unsigned x)
FILE: exercise/ex2-67.c
function int_size_is_32 (line 32) | int int_size_is_32(void)
function int_size_is_at_least_32 (line 50) | int int_size_is_at_least_32(void)
function int_size_is_at_least_16 (line 59) | int int_size_is_at_least_16(void)
FILE: exercise/ex2-68.c
function lower_bits (line 15) | int lower_bits(int x, int n)
FILE: exercise/ex2-69.c
function rotate_right (line 10) | unsigned rotate_right(unsigned x, int n)
FILE: exercise/ex2-7.c
function main (line 13) | int main(void)
FILE: exercise/ex2-70.c
function fits_bits (line 23) | int fits_bits(int x, int n)
FILE: exercise/ex2-71.c
type packed_t (line 39) | typedef unsigned packed_t;
function xbyte (line 41) | int xbyte(packed_t word, int bytenum)
FILE: exercise/ex2-72.c
function copy_int (line 34) | void copy_int(int val, void *buf, int maxbytes)
FILE: exercise/ex2-73.c
function saturating_add (line 31) | int saturating_add(int x, int y)
FILE: exercise/ex2-74.c
function tsub_ovf (line 16) | int tsub_ovf(int x, int y)
FILE: exercise/ex2-75.c
function unsigned_high_prod (line 23) | unsigned unsigned_high_prod(unsigned x, unsigned y)
FILE: exercise/ex2-76.c
function main (line 16) | int main(void)
FILE: exercise/ex2-77.c
function divide_power2 (line 21) | int divide_power2(int x, int k)
FILE: exercise/ex2-78.c
function mul5div8 (line 10) | int mul5div8(int x)
FILE: exercise/ex2-79.c
function fiveeighths (line 31) | int fiveeighths(int x)
FILE: exercise/ex2-80.c
function nlowest_zero (line 15) | int nlowest_zero(int n)
function nlowestone_minus_mlowestone (line 23) | int nlowestone_minus_mlowestone(int n, int m)
FILE: exercise/ex2-81.c
function main (line 31) | int main(void)
FILE: exercise/ex2-83.c
function float_ge (line 50) | int float_ge(float x, float y)
function float_ge_ans (line 79) | int float_ge_ans(float x, float y)
FILE: exercise/ex2-89.c
function f2u (line 20) | unsigned f2u(float f)
function u2f (line 27) | float u2f(unsigned x)
function fpwr2 (line 35) | float fpwr2(int x)
FILE: exercise/ex2-91.c
type float_bits (line 15) | typedef unsigned float_bits;
function float_bits (line 17) | float_bits float_absval(float_bits f)
function f2u (line 38) | unsigned f2u(float f)
function main (line 46) | int main(void)
FILE: exercise/ex2-92.c
type float_bits (line 15) | typedef unsigned float_bits;
function float_bits (line 18) | float_bits float_negate(float_bits f)
FILE: exercise/ex2-93.c
type float_bits (line 15) | typedef unsigned float_bits;
function float_bits (line 18) | float_bits float_half(float_bits f)
FILE: exercise/ex2-94.c
type float_bits (line 15) | typedef unsigned float_bits;
function float_bits (line 18) | float_bits float_twice(float_bits f)
FILE: exercise/ex2-95.c
type float_bits (line 17) | typedef unsigned float_bits;
function float_bits (line 36) | float_bits float_i2f(int i)
FILE: exercise/ex2-96.c
type float_bits (line 19) | typedef unsigned float_bits;
function float_f2i (line 35) | int float_f2i(float_bits f)
FILE: exercise/ex3-19.c
function tmul_ok_32 (line 11) | int tmul_ok_32(int x, int y)
function largest_factorial_32 (line 20) | int largest_factorial_32(void)
function tmul_ok_64 (line 36) | int tmul_ok_64(long long int x, long long int y)
function largest_factorial_64 (line 45) | int largest_factorial_64(void)
FILE: exercise/ex3-34.c
function rfun (line 5) | int rfun(unsigned x)
function main (line 16) | int main(void)
FILE: exercise/ex3-54.c
function decode2 (line 5) | int decode2(int x, int y, int z)
FILE: exercise/ex3-57.c
function cread_alt (line 13) | int cread_alt(int *xp)
FILE: exercise/ex3-58.c
type mode_t (line 6) | typedef enum {
function switch3 (line 14) | int switch3(int *p1, int *p2, mode_t action)
FILE: exercise/ex3-59.c
function switch_prob (line 4) | int switch_prob(int x, int n)
FILE: exercise/ex3-61.c
function var_prod_ele (line 8) | int var_prod_ele(int n, int A[n][n], int B[n][n], int i, int k)
FILE: exercise/ex3-62.c
function transpose (line 10) | void transpose(int M, int A[M][M])
FILE: exercise/ex3-67.c
function proc (line 24) | void proc(union ele *up)
FILE: exercise/ex3-68.c
function good_echo (line 11) | int good_echo(void)
FILE: exercise/ex3-69.c
type ELE (line 9) | struct ELE
type ELE (line 11) | struct ELE {
function trace (line 29) | long trace(tree_ptr tp)
FILE: exercise/ex3-70.c
type ELE (line 9) | struct ELE
type ELE (line 11) | struct ELE {
function traverse (line 20) | long traverse(tree_ptr tp)
FILE: exercise/ex7-7.c
function f (line 13) | void f()
function f (line 22) | void f()
function f (line 34) | void f()
FILE: exercise/ex8-11.c
function main (line 28) | int main()
FILE: exercise/ex8-12.c
function doit (line 12) | void doit()
function main (line 20) | int main()
FILE: exercise/ex8-13.c
function main (line 25) | int main()
FILE: exercise/ex8-14.c
function doit (line 15) | void doit()
function main (line 25) | int main()
FILE: exercise/ex8-15.c
function doit (line 15) | void doit()
function main (line 25) | int main()
FILE: exercise/ex8-16.c
function main (line 12) | int main()
FILE: exercise/ex8-18.c
function end (line 22) | void end(void)
function main (line 27) | int main()
FILE: exercise/ex8-2.c
function main (line 3) | int main()
FILE: exercise/ex8-20.c
function main (line 31) | int main(int argc, char *argv[])
FILE: exercise/ex8-21.c
function main (line 24) | int main()
FILE: exercise/ex8-22.c
function mysystem (line 28) | int mysystem(char *command)
FILE: exercise/ex8-24.c
function main (line 12) | int main(void)
FILE: exercise/ex8-25.c
function signal_handler (line 21) | void signal_handler(int signo)
type sigaction (line 32) | struct sigaction
FILE: exercise/ex8-26/job.c
type job (line 22) | struct job
function is_empty (line 25) | int is_empty(struct job *job_list[], int len)
function init_job (line 35) | void init_job(void)
function free_job (line 56) | void free_job(void)
function add_job (line 64) | int add_job(pid_t pgid, int state, char *command, int len)
function find_job (line 102) | int find_job(pid_t pgid)
function delete_job (line 111) | void delete_job(pid_t pgid)
function update_job (line 120) | void update_job(pid_t pgid, int state)
function pid_t (line 131) | pid_t get_pgid(int jid)
function print_job (line 138) | void print_job(int i)
function print_job_by_pgid (line 153) | void print_job_by_pgid(pid_t pgid)
function print_all_job (line 159) | void print_all_job(void)
function print_foreground (line 171) | void print_foreground(void)
function set_foreground (line 177) | void set_foreground(pid_t pgid, char *command, int len)
function pid_t (line 189) | pid_t foreground_pgid(void)
function get_foreground_command (line 194) | void get_foreground_command(char *command)
function move_to_background (line 200) | void move_to_background(pid_t pgid, int state, char *command, int len)
function move_to_foreground (line 209) | void move_to_foreground(pid_t pgid)
FILE: exercise/ex8-26/job.h
type job (line 17) | struct job {
FILE: exercise/ex8-26/random_fork.c
function pid_t (line 30) | pid_t random_fork(void)
FILE: exercise/ex8-26/shellex.c
function reap_child (line 30) | void reap_child(int signo)
function wait_for_job (line 50) | void wait_for_job(pid_t pgid)
function builtin_command (line 70) | int builtin_command(char **argv)
function parseline (line 109) | int parseline(char *buf, char **argv)
function run_the_job (line 140) | void run_the_job(char *filename, char *argv[], char *env[])
function eval (line 154) | void eval(char *cmdline)
function stop_handler (line 196) | void stop_handler(int signo)
function interrupt_handler (line 208) | void interrupt_handler(int signo)
function install_signal_handler (line 214) | void install_signal_handler(void)
function main (line 255) | int main(void)
FILE: exercise/ex8-26/t-job.c
function main (line 19) | int main(void)
FILE: exercise/ex8-3.c
function main (line 14) | int main(void)
FILE: exercise/ex8-4.c
function main (line 18) | int main()
FILE: exercise/ex8-5.c
function snooze (line 18) | unsigned int snooze(unsigned int secs)
function main (line 28) | int main(void)
FILE: exercise/ex8-6.c
function main (line 11) | int main(int argc, char *argv[])
FILE: exercise/ex8-7.c
function handler (line 20) | void handler(int sig)
function snooze (line 25) | unsigned int snooze(unsigned int secs)
function main (line 39) | int main(int argc, char *argv[])
FILE: exercise/ex8-8.c
function handler1 (line 18) | void handler1(int sig)
function main (line 26) | int main()
FILE: exercise/ex9-14.c
function modify_file_using_mmap (line 19) | int modify_file_using_mmap(int fd)
FILE: exercise/ex9-17.c
function mm_init (line 51) | int mm_init(void)
function mm_free (line 88) | void mm_free(void *bp)
function place (line 182) | static void place(void *bp, size_t asize)
FILE: exercise/ex9-18.c
function mm_init (line 60) | int mm_init(void)
function mm_free (line 97) | void mm_free(void *bp)
function place (line 203) | static void place(void *bp, size_t size)
FILE: exercise/ex9-20/ex9-20.c
type free_block (line 55) | struct free_block {
type free_block (line 65) | struct free_block
function min_block (line 67) | static int min_block(void)
function swap (line 78) | static void swap(struct free_block *b1, struct free_block *b2)
function block_quick_sort (line 90) | static void block_quick_sort(struct free_block *start, struct free_block...
function block_binary_search (line 115) | static long block_binary_search(struct free_block *bs, struct free_block...
function insert_free_block (line 140) | static int insert_free_block(struct free_block *block)
function remove_free_block (line 168) | static void remove_free_block(struct free_block *block)
function adjust_free_block (line 183) | static void adjust_free_block(struct free_block *block)
function coalesce (line 197) | void coalesce(void)
type free_block (line 221) | struct free_block
type free_block (line 226) | struct free_block
function place (line 233) | void place(struct free_block *bp, long asize)
function mo_init (line 250) | int mo_init(void)
type free_block (line 278) | struct free_block
type free_block (line 281) | struct free_block
type free_block (line 290) | struct free_block
type free_block (line 308) | struct free_block
type free_block (line 309) | struct free_block
function mo_free (line 325) | void mo_free(void *ptr)
FILE: exercise/ex9-20/t-block-operate.c
type free_block (line 4) | struct free_block {
type free_block (line 11) | struct free_block
function block_binary_search (line 13) | static long block_binary_search(long size)
function insert_free_block (line 38) | static void insert_free_block(struct free_block *block)
function remove_free_block (line 52) | static void remove_free_block(struct free_block *block)
function adjust_free_block (line 67) | static void adjust_free_block(struct free_block *block)
type free_block (line 82) | struct free_block
function init_blocks (line 84) | static void init_blocks(void)
function print_blocks (line 105) | void print_blocks(void)
function main (line 114) | int main(void)
FILE: exercise/ex9-20/t-block-quick-sort.c
type free_block (line 3) | struct free_block {
type free_block (line 8) | struct free_block
function swap (line 10) | static void swap(struct free_block *b1, struct free_block *b2)
function block_quick_sort (line 22) | static void block_quick_sort(struct free_block *start, struct free_block...
type free_block (line 47) | struct free_block
function init_blocks (line 49) | static void init_blocks(void)
function print_blocks (line 61) | void print_blocks(void)
function main (line 70) | int main(void)
FILE: exercise/ex9-20/t-malloc.c
function main (line 7) | int main(void)
FILE: exercise/ex9-20/t2.c
function main (line 4) | int main(void)
FILE: exercise/ex9-20/t3.c
function main (line 3) | int main(void)
FILE: exercise/ex9-20/t9-20.c
function main (line 21) | int main(void)
FILE: exercise/ex9-5.c
function main (line 25) | int main(int argc, char *argv[])
FILE: exercise/ex9-9.c
function place (line 12) | static void place(void *bp, size_t size)
FILE: exercise/t2-59.c
function main (line 14) | int main(void)
FILE: exercise/t2-95.c
type float_bits (line 17) | typedef unsigned float_bits;
function main (line 22) | int main(void)
FILE: exercise/t2-96.c
type float_bits (line 16) | typedef unsigned float_bits;
function main (line 21) | int main(void)
FILE: exercise/t8-22.c
function main (line 11) | int main(int argc, char *argv[])
FILE: exercise/t8-25.c
function main (line 12) | int main(void)
FILE: exercise/t9-14.c
function main (line 21) | int main(void)
FILE: exercise/t9-17.c
function main (line 16) | int main(void)
FILE: missing.c
type homework (line 30) | struct homework {
type homework (line 36) | struct homework
function init_total_topic (line 50) | int init_total_topic(void)
function index_total (line 62) | int index_total(int chapter_num, int topic_num)
function get_chapter_topic_from_index (line 78) | void get_chapter_topic_from_index(int index, int *chapter_num, int *topi...
function get_chapter_topic_from_filename (line 95) | void get_chapter_topic_from_filename(char *filename, int *chapter_num, i...
function set_total_topic (line 128) | void set_total_topic(char *dirname)
function main (line 152) | int main(void)
FILE: sample/ch02/show-bytes.c
function show_bytes (line 13) | void show_bytes(byte_pointer start, int len)
function show_int (line 21) | void show_int(int x)
function show_float (line 26) | void show_float(float x)
function show_pointer (line 31) | void show_pointer(void *x)
FILE: sample/ch03/buf-overflow.c
function echo (line 20) | void echo()
FILE: sample/ch03/code.c
function sum (line 13) | int sum(int x, int y)
FILE: sample/ch03/main.c
function main (line 7) | int main()
FILE: sample/ch03/simple.c
function simple (line 7) | int simple(int *xp, int y)
FILE: sample/ch03/simple_1.c
function simple_1 (line 9) | long int simple_1(long int *xp, long int y)
FILE: sample/ch07/addvec.c
function addvec (line 8) | void addvec(int *x, int *y, int *z, int n)
FILE: sample/ch07/bar1.c
function main (line 4) | int main()
FILE: sample/ch07/bar2.c
function f (line 6) | void f()
FILE: sample/ch07/bar3.c
function f (line 6) | void f()
FILE: sample/ch07/bar4.c
function f (line 7) | void f()
FILE: sample/ch07/bar5.c
function f (line 7) | void f()
FILE: sample/ch07/dll.c
function main (line 16) | int main()
FILE: sample/ch07/foo1.c
function main (line 5) | int main()
FILE: sample/ch07/foo2.c
function main (line 6) | int main()
FILE: sample/ch07/foo3.c
function main (line 10) | int main()
FILE: sample/ch07/foo4.c
function main (line 11) | int main()
FILE: sample/ch07/foo5.c
function main (line 20) | int main()
FILE: sample/ch07/linkerror.c
function main (line 7) | int main(void)
FILE: sample/ch07/main.c
function main (line 9) | int main()
FILE: sample/ch07/main2.c
function main (line 17) | int main()
FILE: sample/ch07/multvec.c
function multvec (line 5) | void multvec(int *x, int *y, int *z, int n)
FILE: sample/ch07/swap.c
function swap (line 10) | void swap()
FILE: sample/ch08/alarm.c
function handler (line 17) | void handler(int sig)
function main (line 30) | int main()
FILE: sample/ch08/fork.c
function main (line 10) | int main()
FILE: sample/ch08/kill.c
function main (line 11) | int main()
FILE: sample/ch08/procmask1.c
function handler (line 41) | void handler(int sig)
function main (line 50) | int main(int argc, char **argv)
FILE: sample/ch08/procmask2.c
function handler (line 17) | void handler(int sig)
function main (line 26) | int main(int argc, char **argv)
FILE: sample/ch08/restart.c
function handler (line 22) | void handler(int sig)
function main (line 27) | int main()
FILE: sample/ch08/rfork.c
function pid_t (line 30) | pid_t Fork(void)
FILE: sample/ch08/setjmp.c
function main (line 25) | int main()
function foo (line 42) | void foo(void)
function bar (line 49) | void bar(void)
FILE: sample/ch08/shellex.c
function main (line 15) | int main()
function eval (line 32) | void eval(char *cmdline)
function builtin_command (line 65) | int builtin_command(char **argv)
function parseline (line 75) | int parseline(char *buf, char **argv)
FILE: sample/ch08/sigint1.c
function handler (line 13) | void handler(int sig) /* SIGINT handler */
function main (line 19) | int main()
FILE: sample/ch08/signal1.c
function handler1 (line 28) | void handler1(int sig)
function main (line 39) | int main()
FILE: sample/ch08/signal2.c
function handler2 (line 22) | void handler2(int sig)
function main (line 34) | int main()
FILE: sample/ch08/signal3.c
function handler2 (line 14) | void handler2(int sig)
function main (line 26) | int main()
FILE: sample/ch08/signal4.c
function handler2 (line 11) | void handler2(int sig)
function main (line 23) | int main()
FILE: sample/ch08/waitpid1.c
function main (line 10) | int main(void)
FILE: sample/ch08/waitpid2.c
function main (line 10) | int main(void)
FILE: sample/ch09/memlib.c
function mem_init (line 13) | void mem_init(void)
FILE: sample/ch09/mm-test.c
function main (line 8) | int main(void)
FILE: sample/ch09/mm.c
function mm_init (line 40) | int mm_init(void)
function mm_free (line 76) | void mm_free(void *bp)
function place (line 167) | static void place(void *bp, size_t asize)
FILE: sample/ch10/cpfile.c
function main (line 11) | int main(int argc, char *argv[])
FILE: sample/ch10/cpstdin.c
function main (line 9) | int main(void)
FILE: sample/ch10/statcheck.c
function main (line 9) | int main(int argc, char **argv)
FILE: sample/ch11/echo.c
function echo (line 11) | void echo(int connfd)
FILE: sample/ch11/echoclient.c
function main (line 12) | int main(int argc, char **argv)
FILE: sample/ch11/echoserveri.c
function main (line 13) | int main(int argc, char **argv)
FILE: sample/ch11/hostinfo.c
function main (line 18) | int main(int argc, char **argv)
FILE: sample/ch11/tiny/cgi-bin/adder.c
function main (line 9) | int main(void)
FILE: sample/ch11/tiny/tiny.c
function main (line 19) | int main(int argc, char **argv)
function doit (line 40) | void doit(int fd)
function clienterror (line 85) | void clienterror(int fd, char *cause, char *errnum,
function read_requesthdrs (line 107) | void read_requesthdrs(rio_t *rp)
function parse_uri (line 119) | int parse_uri(char *uri, char *filename, char *cgiargs)
function serve_static (line 145) | void serve_static(int fd, char *filename, int filesize)
function get_filetype (line 169) | void get_filetype(char *filename, char *filetype)
function serve_dynamic (line 181) | void serve_dynamic(int fd, char *filename, char *cgiargs)
FILE: sample/ch12/badcnt.c
function main (line 22) | int main(int argc, char **argv)
FILE: sample/ch12/echo_cnt.c
function init_echo_cnt (line 14) | static void init_echo_cnt(void)
function echo_cnt (line 20) | void echo_cnt(int connfd)
FILE: sample/ch12/echoserverp.c
function sigchld_handler (line 16) | void sigchld_handler(int sig)
function main (line 23) | int main(int argc, char **argv)
FILE: sample/ch12/echoservers.c
type pool (line 13) | typedef struct { /* Represents a pool of connected descri...
function init_pool (line 28) | void init_pool(int listenfd, pool *p)
function add_client (line 42) | void add_client(int connfd, pool *p)
function check_client (line 66) | void check_client(pool *p)
function main (line 96) | int main(int argc, char **argv)
FILE: sample/ch12/echoservert.c
function main (line 15) | int main(int argc, char **argv)
FILE: sample/ch12/echoservert_pre.c
function main (line 31) | int main(int argc, char **argv)
FILE: sample/ch12/goodcnt.c
function main (line 20) | int main(int argc, char **argv)
FILE: sample/ch12/hello.c
function main (line 16) | int main()
FILE: sample/ch12/sbuf.c
function sbuf_init (line 9) | void sbuf_init(sbuf_t *sp, int n)
function sbuf_deinit (line 20) | void sbuf_deinit(sbuf_t *sp)
function sbuf_insert (line 26) | void sbuf_insert(sbuf_t *sp, int item)
function sbuf_remove (line 36) | int sbuf_remove(sbuf_t *sp)
FILE: sample/ch12/sbuf.h
type sbuf_t (line 10) | typedef struct {
FILE: sample/ch12/select.c
function main (line 18) | int main(int argc, char **argv)
function command (line 51) | void command(void)
FILE: sample/ch12/sharing.c
function main (line 22) | int main()
Condensed preview — 332 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,109K chars).
[
{
"path": ".gitignore",
"chars": 180,
"preview": "test.c\nt.c\na.out\nmissing\n\nTAGS\ntags\n\n# Object files\n*.o\n*.s\n\n# Libraries\n*.lib\n*.a\n\n# Shared objects (inc. Windows DLLs)"
},
{
"path": "README",
"chars": 969,
"preview": "================================================================================\n 深入理解计算机系统·第二版\n Randal E."
},
{
"path": "bin/d2h",
"chars": 240,
"preview": "#!/usr/bin/perl\n# Convert list of decimal numbers into hex\n\n# 将十进制数字转化为十六进制数字\n# 用法:\n# $ ./d2h 100 500 751\n# 100="
},
{
"path": "bin/h2d",
"chars": 264,
"preview": "#!/usr/bin/perl\n# Convert list of hex numbers into decimal\n\n# 将十六进制数字转化为十进制数字\n# 用法:\n# $ ./h2d 100 0x500 0x751\n# "
},
{
"path": "code/conc/badcnt.c",
"chars": 1044,
"preview": "/* \n * badcnt.c - An improperly synchronized counter program \n */\n/* $begin badcnt */\n#include \"csapp.h\"\n\nvoid *thread(v"
},
{
"path": "code/conc/ctime_ts.c",
"chars": 722,
"preview": "/* \n * ctime_ts - A thread-safe wrapper for ctime\n */\n#include \"csapp.h\"\n#define MAXSTR 128\n\nstatic sem_t mutex; /* prot"
},
{
"path": "code/conc/echo_cnt.c",
"chars": 921,
"preview": "/* \n * A thread-safe version of echo that counts the total number\n * of bytes received from clients.\n */\n/* $begin echo_"
},
{
"path": "code/conc/echoserverp.c",
"chars": 1167,
"preview": "/* \n * echoserverp.c - A concurrent echo server based on processes\n */\n/* $begin echoserverpmain */\n#include \"csapp.h\"\nv"
},
{
"path": "code/conc/echoservers.c",
"chars": 4430,
"preview": "/* \n * echoservers.c - A concurrent echo server based on select\n */\n/* $begin echoserversmain */\n#include \"csapp.h\"\n\ntyp"
},
{
"path": "code/conc/echoservert.c",
"chars": 1028,
"preview": "/* \n * echoservert.c - A concurrent echo server using threads\n */\n/* $begin echoservertmain */\n#include \"csapp.h\"\n\nvoid "
},
{
"path": "code/conc/echoservert_pre.c",
"chars": 1287,
"preview": "/* \n * echoservert_pre.c - A prethreaded concurrent echo server\n */\n/* $begin echoservertpremain */\n#include \"csapp.h\"\n#"
},
{
"path": "code/conc/hello.c",
"chars": 810,
"preview": "/* \n * hello.c - Pthreads \"hello, world\" program \n */\n/* $begin hello */\n#include \"csapp.h\"\nvoid *thread(void *vargp); "
},
{
"path": "code/conc/hellobug.c",
"chars": 358,
"preview": "/* \n * hellobug.c - \"hello, world\" program with a bug\n */\n/* $begin hellobug */\n#include \"csapp.h\"\nvoid *thread(void *va"
},
{
"path": "code/conc/norace.c",
"chars": 739,
"preview": "/* \n * norace.c - fixes the race in race.c\n */\n/* $begin norace */\n#include \"csapp.h\"\n#define N 4\n\nvoid *thread(void *va"
},
{
"path": "code/conc/psum.c",
"chars": 2547,
"preview": "/* \n * psum.c - A simple parallel sum program\n */\n/* $begin psum */\n#include \"csapp.h\"\n#define MAXTHREADS 32 \n\nvoid *"
},
{
"path": "code/conc/race.c",
"chars": 541,
"preview": "/* \n * race.c - demonstrates a race condition\n */\n/* $begin race */\n#include \"csapp.h\"\n#define N 4\n\nvoid *thread(void *v"
},
{
"path": "code/conc/rand.c",
"chars": 471,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n\n/* $begin rand */\nunsigned int next = 1;\n\n/* rand - return pseudo-random integer"
},
{
"path": "code/conc/rand_r.c",
"chars": 431,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n\n/* $begin rand_r */\n/* rand_r - a reentrant pseudo-random integer on 0..32767 */"
},
{
"path": "code/conc/sbuf.c",
"chars": 1763,
"preview": "/* $begin sbufc */\n#include \"csapp.h\"\n#include \"sbuf.h\"\n\n/* Create an empty, bounded, shared FIFO buffer with n slots */"
},
{
"path": "code/conc/sbuf.h",
"chars": 658,
"preview": "#ifndef __SBUF_H__\n#define __SBUF_H__\n\n#include \"csapp.h\"\n\n/* $begin sbuft */\ntypedef struct {\n int *buf; /*"
},
{
"path": "code/conc/select.c",
"chars": 1373,
"preview": "/* $begin select */\n#include \"csapp.h\"\nvoid echo(int connfd);\nvoid command(void);\n\nint main(int argc, char **argv) \n{\n "
},
{
"path": "code/conc/sharing.c",
"chars": 622,
"preview": "/* $begin sharing */\n#include \"csapp.h\"\n#define N 2\nvoid *thread(void *vargp);\n\nchar **ptr; /* global variable */ //lin"
},
{
"path": "code/conc/tfgets-main.c",
"chars": 263,
"preview": "/* $begin tfgetsmain */\n#include \"csapp.h\"\n\nchar *tfgets(char *s, int size, FILE *stream);\n\nint main() \n{\n char buf[M"
},
{
"path": "code/data/show-bytes.c",
"chars": 2632,
"preview": "/* $begin show-bytes */\n#include <stdio.h>\n/* $end show-bytes */\n#include <stdlib.h>\n#include <string.h>\n/* $begin show-"
},
{
"path": "code/ecf/alarm.c",
"chars": 488,
"preview": "/* $begin alarm */\n#include \"csapp.h\"\n\nvoid handler(int sig) \n{\n static int beeps = 0;\n\n printf(\"BEEP\\n\");\n if "
},
{
"path": "code/ecf/counterprob.c",
"chars": 470,
"preview": "/* $begin counterprob */\n#include \"csapp.h\"\n\nint counter = 0;\n\nvoid handler(int sig) \n{\n counter++;\n sleep(1); /* "
},
{
"path": "code/ecf/fork.c",
"chars": 334,
"preview": "/* $begin fork */\n#include \"csapp.h\"\n\nint main() \n{\n pid_t pid;\n int x = 1;\n\n pid = Fork(); //line:ecf:forkretu"
},
{
"path": "code/ecf/forkprob0.c",
"chars": 200,
"preview": "/* $begin forkprob0 */\n#include \"csapp.h\"\n\nint main() \n{\n int x = 1;\n\n if (Fork() == 0)\n\tprintf(\"printf1: x=%d\\n\","
},
{
"path": "code/ecf/forkprob1.c",
"chars": 166,
"preview": "/* $begin forkprob1 */\n#include \"csapp.h\"\n\nint main() \n{\n int i;\n\n for (i = 0; i < 2; i++) \n\tFork();\n printf(\"h"
},
{
"path": "code/ecf/forkprob2.c",
"chars": 227,
"preview": "/* $begin forkprob2 */\n#include \"csapp.h\"\n\nvoid end(void) \n{\n printf(\"2\"); \n}\n\nint main() \n{\n if (Fork() == 0) \n\ta"
},
{
"path": "code/ecf/forkprob3.c",
"chars": 183,
"preview": "/* $begin forkprob3 */\n#include \"csapp.h\"\n\nint main() \n{\n int x = 3;\n\n if (Fork() != 0)\n\tprintf(\"x=%d\\n\", ++x);\n\n "
},
{
"path": "code/ecf/forkprob4.c",
"chars": 207,
"preview": "/* $begin forkprob4 */\n#include \"csapp.h\"\n\nvoid doit() \n{\n Fork();\n Fork();\n printf(\"hello\\n\");\n return;\n}\n\n"
},
{
"path": "code/ecf/forkprob5.c",
"chars": 226,
"preview": "/* $begin forkprob5 */\n#include \"csapp.h\"\n\nvoid doit() \n{\n if (Fork() == 0) {\n\tFork();\n\tprintf(\"hello\\n\");\n\texit(0);\n"
},
{
"path": "code/ecf/forkprob6.c",
"chars": 225,
"preview": "/* $begin forkprob6 */\n#include \"csapp.h\"\n\nvoid doit() \n{\n if (Fork() == 0) {\n\tFork();\n\tprintf(\"hello\\n\");\n\treturn;\n "
},
{
"path": "code/ecf/forkprob7.c",
"chars": 232,
"preview": "/* $begin forkprob7 */\n#include \"csapp.h\"\nint counter = 1;\n\nint main() \n{\n if (fork() == 0) {\n\tcounter--; \n\texit(0);"
},
{
"path": "code/ecf/forkprob8.c",
"chars": 319,
"preview": "#include \"csapp.h\"\n\n/* $begin forkprob8 */\nvoid foo(int n) \n{\n int i;\n\n for (i = 0; i < n; i++) \n\tFork();\n prin"
},
{
"path": "code/ecf/hello-asm.sa",
"chars": 578,
"preview": "/* $begin hello-s 1 */\n.section .data\nstring:\n\t.ascii \"hello, world\\n\"\nstring_end:\n\t.equ len, string_end - string\n\n.sect"
},
{
"path": "code/ecf/kill.c",
"chars": 386,
"preview": "/* $begin kill */\n#include \"csapp.h\"\n\nint main() \n{\n pid_t pid;\n\n /* Child sleeps until SIGKILL signal received, t"
},
{
"path": "code/ecf/procmask1.c",
"chars": 696,
"preview": "#include \"csapp.h\"\n\nvoid initjobs()\n{\n}\n\nvoid addjob(int pid)\n{\n}\n\nvoid deletejob(int pid)\n{\n}\n\n/* $begin procmask1 */\nv"
},
{
"path": "code/ecf/procmask2.c",
"chars": 957,
"preview": "#include \"csapp.h\"\n\nvoid initjobs()\n{\n}\n\nvoid addjob(int pid)\n{\n}\n\nvoid deletejob(int pid)\n{\n}\n\n/* $begin procmask2 */\nv"
},
{
"path": "code/ecf/restart.c",
"chars": 336,
"preview": "/* $begin restart */\n#include \"csapp.h\"\n\nsigjmp_buf buf;\n\nvoid handler(int sig) \n{\n siglongjmp(buf, 1);\n}\n\nint main()"
},
{
"path": "code/ecf/rfork.c",
"chars": 1215,
"preview": "/*\n * rfork.c - Wrapper for fork() that introduces non-determinism\n * in the order that the parent and child a"
},
{
"path": "code/ecf/setjmp.c",
"chars": 580,
"preview": "/* $begin setjmp */\n#include \"csapp.h\"\n\njmp_buf buf;\n\nint error1 = 0; \nint error2 = 1;\n\nvoid foo(void), bar(void);\n\nint "
},
{
"path": "code/ecf/shellex.c",
"chars": 2502,
"preview": "/* $begin shellmain */\n#include \"csapp.h\"\n#define MAXARGS 128\n\n/* function prototypes */\nvoid eval(char *cmdline);\nint"
},
{
"path": "code/ecf/sigint1.c",
"chars": 676,
"preview": "/* $begin sigint1 */\n#include \"csapp.h\"\n\nvoid handler(int sig) /* SIGINT handler */ //line:ecf:sigint1:beginhandler\n{\n"
},
{
"path": "code/ecf/signal1.c",
"chars": 775,
"preview": "/* $begin signal1 */\n#include \"csapp.h\"\n\nvoid handler1(int sig) \n{\n pid_t pid;\n\n if ((pid = waitpid(-1, NULL, 0)) "
},
{
"path": "code/ecf/signal2.c",
"chars": 806,
"preview": "/* $begin signal2 */\n#include \"csapp.h\"\n\nvoid handler2(int sig) \n{\n pid_t pid;\n \n while ((pid = waitpid(-1, NULL,"
},
{
"path": "code/ecf/signal3.c",
"chars": 858,
"preview": "/* $begin signal3 */\n#include \"csapp.h\"\n\nvoid handler2(int sig) \n{\n pid_t pid;\n \n while ((pid = waitpid(-1, NULL,"
},
{
"path": "code/ecf/signal4.c",
"chars": 827,
"preview": "/* $begin signal4 */\n#include \"csapp.h\"\n\nvoid handler2(int sig) \n{\n pid_t pid;\n \n while ((pid = waitpid(-1, NULL,"
},
{
"path": "code/ecf/signalprob0.c",
"chars": 555,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <wait.h>\n#include <signal.h>\n\n/* $begin signalprob0 "
},
{
"path": "code/ecf/waitpid1.c",
"chars": 972,
"preview": "/* $begin waitpid1 */\n#include \"csapp.h\"\n#define N 2\n\nint main() \n{\n int status, i;\n pid_t pid;\n\n /* Parent cre"
},
{
"path": "code/ecf/waitpid2.c",
"chars": 779,
"preview": "/* $begin waitpid2 */\n#include \"csapp.h\"\n#define N 2\n\nint main() \n{\n int status, i;\n pid_t pid[N], retpid;\n\n /*"
},
{
"path": "code/ecf/waitprob0.c",
"chars": 207,
"preview": "#include \"csapp.h\"\n\n/* $begin waitprob0 */\nint main() \n{\n if (Fork() == 0) {\n\tprintf(\"a\");\n }\n else {\n\tprintf(\""
},
{
"path": "code/ecf/waitprob1.c",
"chars": 352,
"preview": "#include \"csapp.h\"\n\n/* $begin waitprob1 */\nint main() \n{\n int status;\n pid_t pid;\n \n printf(\"Hello\\n\");\n pi"
},
{
"path": "code/ecf/waitprob3.c",
"chars": 219,
"preview": "#include \"csapp.h\"\n\n/* $begin waitprob3 */\nint main() \n{\n if (fork() == 0) {\n\tprintf(\"a\");\n\texit(0);\n } \n else"
},
{
"path": "code/include/csapp.h",
"chars": 5581,
"preview": "/* $begin csapp.h */\n#ifndef __CSAPP_H__\n#define __CSAPP_H__\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>"
},
{
"path": "code/intro/hello.c",
"chars": 103,
"preview": "/* $begin hello */\n#include <stdio.h>\n\nint main() \n{\n printf(\"hello, world\\n\");\n}\n/* $end hello */\n\n"
},
{
"path": "code/io/cpfile.c",
"chars": 339,
"preview": "/* $begin cpfile */\n#include \"csapp.h\"\n\nint main(int argc, char **argv) \n{\n int n;\n rio_t rio;\n char buf[MAXLIN"
},
{
"path": "code/io/cpstdin.c",
"chars": 179,
"preview": "/* $begin cpstdin */\n#include \"csapp.h\"\n\nint main(void) \n{\n char c;\n\n while(Read(STDIN_FILENO, &c, 1) != 0) \n\tWrit"
},
{
"path": "code/io/statcheck.c",
"chars": 646,
"preview": "/* $begin statcheck */\n#include \"csapp.h\"\n\nint main (int argc, char **argv) \n{\n struct stat stat;\n char *type, *re"
},
{
"path": "code/link/addvec.c",
"chars": 168,
"preview": "/* addvec.c */\n/* $begin addvec */\nvoid addvec(int *x, int *y,\n\t int *z, int n) \n{\n int i;\n\n for (i = 0; i < n;"
},
{
"path": "code/link/dll.c",
"chars": 890,
"preview": "/* $begin dll */\n#include <stdio.h>\n#include <stdlib.h>\n#include <dlfcn.h>\n\nint x[2] = {1, 2};\nint y[2] = {3, 4};\nint z["
},
{
"path": "code/link/elfstructs.c",
"chars": 728,
"preview": "/* $begin elfsymbol */\ntypedef struct { \n int name; /* string table offset */ \n int value; /* section"
},
{
"path": "code/link/main.c",
"chars": 126,
"preview": "/* $begin main */\n/* main.c */\nvoid swap();\n\nint buf[2] = {1, 2};\n\nint main() \n{\n swap();\n return 0;\n}\n/* $end mai"
},
{
"path": "code/link/main2.c",
"chars": 235,
"preview": "/* $begin main2 */\n/* main2.c */\n#include <stdio.h>\n#include \"vector.h\"\n\nint x[2] = {1, 2};\nint y[2] = {3, 4};\nint z[2];"
},
{
"path": "code/link/multvec.c",
"chars": 174,
"preview": "/* multvec.c */\n/* $begin multvec */\nvoid multvec(int *x, int *y, \n\t int *z, int n) \n{\n int i;\n\n for (i = 0; i"
},
{
"path": "code/link/p-exe.d",
"chars": 17067,
"preview": "\np: file format elf32-i386\np\narchitecture: i386, flags 0x00000112:\nEXEC_P, HAS_SYMS, D_PAGED\nstart address 0x080482f"
},
{
"path": "code/link/pdata-exe.d",
"chars": 9131,
"preview": "\np: file format elf32-i386\np\narchitecture: i386, flags 0x00000112:\nEXEC_P, HAS_SYMS, D_PAGED\nstart address 0x080482f"
},
{
"path": "code/link/swap.c",
"chars": 214,
"preview": "/* $begin swap */\n/* swap.c */\nextern int buf[];\n\nint *bufp0 = &buf[0];\nint *bufp1;\n\nvoid swap() \n{\n int temp;\n\n b"
},
{
"path": "code/mem/matmult/mm.c",
"chars": 3630,
"preview": "/* matrix multiply permutations */\n#include <stdio.h>\n#include <stdlib.h>\n#include \"mm.h\"\n#include \"fcycmm.h\"\n#include \""
},
{
"path": "code/mem/mountain/mountain.c",
"chars": 2891,
"preview": "/* mountain.c - Generate the memory mountain. */\n/* $begin mountainmain */\n#include <stdlib.h>\n#include <stdio.h>\n#inclu"
},
{
"path": "code/netp/echo.c",
"chars": 399,
"preview": "/*\n * echo - read and echo text lines until client closes connection\n */\n/* $begin echo */\n#include \"csapp.h\"\n\nvoid echo"
},
{
"path": "code/netp/echoclient.c",
"chars": 655,
"preview": "/*\n * echoclient.c - An echo client\n */\n/* $begin echoclientmain */\n#include \"csapp.h\"\n\nint main(int argc, char **argv) "
},
{
"path": "code/netp/echoserveri.c",
"chars": 902,
"preview": "/* \n * echoserveri.c - An iterative echo server \n */ \n/* $begin echoserverimain */\n#include \"csapp.h\"\n\nvoid echo(int con"
},
{
"path": "code/netp/hostinfo.c",
"chars": 768,
"preview": "/* $begin hostinfo */\n#include \"csapp.h\"\n\nint main(int argc, char **argv) \n{\n char **pp;\n struct in_addr addr;\n "
},
{
"path": "code/netp/tiny/cgi-bin/adder.c",
"chars": 963,
"preview": "/*\n * adder.c - a minimal CGI program that adds two numbers together\n */\n/* $begin adder */\n#include \"csapp.h\"\n\nint main"
},
{
"path": "code/netp/tiny/tiny.c",
"chars": 8115,
"preview": "/* $begin tinymain */\n/*\n * tiny.c - A simple, iterative HTTP/1.0 Web server that uses the \n * GET method to serve s"
},
{
"path": "code/src/csapp.c",
"chars": 17714,
"preview": "/* $begin csapp.c */\n#include \"csapp.h\"\n\n/************************** \n * Error-handling functions\n *********************"
},
{
"path": "code/vm/malloc/memlib.c",
"chars": 2089,
"preview": "/*\n * memlib.c - a module that simulates the memory system. Needed\n * because it allows us to interleave calls from the"
},
{
"path": "code/vm/malloc/mm.c",
"chars": 10790,
"preview": "/* \n * Simple, 32-bit and 64-bit clean allocator based on implicit free\n * lists, first fit placement, and boundary tag "
},
{
"path": "code/vm/memlib.h",
"chars": 53,
"preview": "void *mem_init(int size);\nvoid *mem_sbrk(int incr);\n\n"
},
{
"path": "code/vm/mm.h",
"chars": 394,
"preview": "/* $begin mallocinterface */\nint mm_init(void); \nvoid *mm_malloc(size_t size); \nvoid mm_free(void *bp);\n/* $end mallocin"
},
{
"path": "common/csapp.c",
"chars": 18529,
"preview": "/* $begin csapp.c */\n#include \"csapp.h\"\n\n/**************************\n * Error-handling functions\n **********************"
},
{
"path": "common/csapp.h",
"chars": 5575,
"preview": "/* $begin csapp.h */\n#ifndef __CSAPP_H__\n#define __CSAPP_H__\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>"
},
{
"path": "exercise/00-topic.txt",
"chars": 52654,
"preview": "================================================================================\n这个文件收集了《深入理解计算机系统·第二版》的家庭作业的题目。关于这本书的详细"
},
{
"path": "exercise/README",
"chars": 119,
"preview": "这个文件对这个文件夹下面的文件做出说明。\n\n00-topic.txt: 这个文件收集了这本书的所有的家庭作业的题目\nex*: 其他的所有文件都是题目的解答\nt*: 以 t 为前缀的文件是对题目的测试\n\nmofaph\n2012/11/24\n"
},
{
"path": "exercise/ex10-10.c",
"chars": 971,
"preview": "/*\n * 10.10\n *\n * mofaph@gmail.com\n * 2013-5-11\n *\n * 感谢 @oymy,指出了这道题应该使用 dup2()。\n *\n * $ cc -I../common ../common/csapp"
},
{
"path": "exercise/ex10-2.c",
"chars": 468,
"preview": "/*\n * 10.2\n *\n * mofaph@gmail.com\n *\n * 假设磁盘文件 foobar.txt 由 6 个 ASCII 码字符“foobar”组成。那么,下列程序的输\n * 出是什么?\n *\n * $ echo \"foo"
},
{
"path": "exercise/ex10-3.c",
"chars": 530,
"preview": "/*\n * 10.3\n *\n * 就像前面 10.2 那样,假设磁盘文件 foobar.txt 由 6 个 ASCII 码字符“foobar”组成。\n * 那么下列程序的输出是什么?\n *\n * $ echo \"foobar\" > foob"
},
{
"path": "exercise/ex10-5.c",
"chars": 491,
"preview": "/*\n * 10.5\n *\n * mofaph@gmail.com\n *\n * 假设磁盘文件 foobar.txt 由 6 个 ASCII 码字符“foobar”组成,那么下列程序的输出\n * 是什么?\n *\n * $ echo \"foob"
},
{
"path": "exercise/ex10-6.c",
"chars": 464,
"preview": "/*\n * 10.6\n *\n * mofaph@gmail.com\n * 2013/5/11\n *\n * 下面程序的输出是什么?\n *\n * $ touch {foo,bar,baz}.txt\n * $ cc -I../common ../"
},
{
"path": "exercise/ex10-7.c",
"chars": 899,
"preview": "/*\n * 10.7\n *\n * mofaph@gmail.com\n * 2013-5-11\n *\n * $ cc -I../common ../common/csapp.c ex10-7.c -lpthread\n * # 注意,上面链接到"
},
{
"path": "exercise/ex10-8.c",
"chars": 1411,
"preview": "/*\n * 10.8\n *\n * mofaph@gmail.com\n * 2013-5-11\n *\n * 编写图 10-10 中的 statcheck 程序的一个版本,叫做 fstatcheck,它从命令行取得一\n * 个描述符数字而不是文"
},
{
"path": "exercise/ex10-9.txt",
"chars": 648,
"preview": "10.9\n\nbskim45@gmail.com\n2013-12-17\n--------------------------------------------------------------------------------\n\nBef"
},
{
"path": "exercise/ex11-10/cgi-bin/adder.c",
"chars": 2021,
"preview": "/*\n * 11.10\n *\n * mofaph@gmail.com\n * 2013-5-31\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthre"
},
{
"path": "exercise/ex11-10/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-10/tiny.c",
"chars": 10172,
"preview": "/*\n * 11.10\n *\n * mofaph@gmail.com\n * 2013-5-31\n *\n * unix> cc -Wall -I../../common ../../common/csapp.c tiny.c -lpthrea"
},
{
"path": "exercise/ex11-11/cgi-bin/adder.c",
"chars": 2246,
"preview": "/*\n * 11.11\n *\n * mofaph@gmail.com\n * 2013-6-8\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthrea"
},
{
"path": "exercise/ex11-11/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-11/tiny.c",
"chars": 10823,
"preview": "/*\n * 11.11\n *\n * mofaph@gmail.com\n * 2013-6-4\n *\n * unix> cc -Wall -I../../common ../../common/csapp.c tiny.c -lpthread"
},
{
"path": "exercise/ex11-12/cgi-bin/adder.c",
"chars": 2278,
"preview": "/*\n * 11.12\n *\n * mofaph@gmail.com\n * 2013-6-11\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthre"
},
{
"path": "exercise/ex11-12/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-12/tiny.c",
"chars": 11893,
"preview": "/*\n * 11.12\n *\n * mofaph@gmail.com\n * 2013-6-11\n *\n * unix> cc -Wall -I../../common ../../common/csapp.c tiny.c -lpthrea"
},
{
"path": "exercise/ex11-13/cgi-bin/adder.c",
"chars": 2278,
"preview": "/*\n * 11.12\n *\n * mofaph@gmail.com\n * 2013-6-11\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthre"
},
{
"path": "exercise/ex11-13/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-13/tiny.c",
"chars": 13200,
"preview": "/*\n * 11.13\n *\n * mofaph@gmail.com\n * 2013-6-22\n *\n * 如果一个服务器写一个已经被客户端关闭了的连接(比如,在浏览器上单击了“Stop”按\n * 钮),那么第一次这样的写会正常返回,但是第"
},
{
"path": "exercise/ex11-2.c",
"chars": 949,
"preview": "/*\n * 11.2\n *\n * mofaph@gmail.com\n * 2013-5-13\n *\n * 编写程序 hex2dd.c,它将十六进制参数转换为点分十进制串并打印出结果。例如:\n *\n * unix> cc ex11-2.c -"
},
{
"path": "exercise/ex11-3.c",
"chars": 872,
"preview": "/*\n * 11.3\n *\n * mofaph@gmail.com\n * 2013-5-13\n *\n * 编写程序 dd2hex.c,它将它的点分十进制参数转换为十六进制数并打印出结果。例如\n *\n * unix> cc ex11-3.c "
},
{
"path": "exercise/ex11-6/cgi-bin/adder.c",
"chars": 1106,
"preview": "/*\n * p638\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthread -o adder\n */\n\n#include \"csapp.h\"\n\n"
},
{
"path": "exercise/ex11-6/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-6/tiny.c",
"chars": 7683,
"preview": "/*\n * 11.6\n *\n * mofaph@gmail.com\n * 2013-5-25\n *\n * unix> cc -Wall -I../../common ../../common/csapp.c tiny.c -lpthread"
},
{
"path": "exercise/ex11-7/cgi-bin/adder.c",
"chars": 2019,
"preview": "/*\n * 11.7\n *\n * mofaph@gmail.com\n * 2013-6-2\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthread"
},
{
"path": "exercise/ex11-7/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-7/tiny.c",
"chars": 10261,
"preview": "/*\n * 11.7\n *\n * mofaph@gmail.com\n * 2013-6-2\n *\n * unix> cc -Wall -I../../common ../../common/csapp.c tiny.c -lpthread "
},
{
"path": "exercise/ex11-8/cgi-bin/adder.c",
"chars": 1158,
"preview": "/*\n * p638\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthread -o adder\n */\n\n#include \"csapp.h\"\n\n"
},
{
"path": "exercise/ex11-8/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-8/tiny.c",
"chars": 8903,
"preview": "/*\n * 11.8\n *\n * mofaph@gmail.com\n * 2013-5-28\n *\n * 如果要使用信号处理程序来回收终止的子进程,需要注意的问题是“待处理信号”的问题。\n * 由于 UNIX 系统在同一个时刻中,只会保留一"
},
{
"path": "exercise/ex11-9/cgi-bin/adder.c",
"chars": 1158,
"preview": "/*\n * p638\n *\n * unix> cc -I../../../common ../../../common/csapp.c adder.c -lpthread -o adder\n */\n\n#include \"csapp.h\"\n\n"
},
{
"path": "exercise/ex11-9/home.html",
"chars": 19,
"preview": "Welcome to add.com\n"
},
{
"path": "exercise/ex11-9/tiny.c",
"chars": 10374,
"preview": "/*\n * 11.9\n *\n * mofaph@gmail.com\n * 2013-5-29\n *\n * 1. 打开文件\n * 2. 将文件内容读入缓冲区\n * 3. 将缓冲区内容传送到客户端\n * 4. 判断文件是否还有内容\n * 5. "
},
{
"path": "exercise/ex12-22.c",
"chars": 4685,
"preview": "/*\n * 12.22\n *\n * mofaph@gmail.com\n * 2013-8-17\n *\n * 使用 I/O 多路复用的 echo 服务器。服务器使用 select 等待监听描述符上的连接请求\n * 和标准输入上的命令。\n *\n"
},
{
"path": "exercise/ex2-36.c",
"chars": 578,
"preview": "/*\n * 练习题 2.36\n *\n * 对于数据类型 int 为 32 位的情况,设计一个版本的 tmult_ok 函数(见练习题 2.35),\n * 要使用 64 位精度的数据类型 long long,而不使用除法。\n */\n\n/*\n "
},
{
"path": "exercise/ex2-42.c",
"chars": 617,
"preview": "/*\n * 练习题 2.42\n *\n * 写一个函数 div16,对于整数参数 x 返回 x/16 的值。你的函数不能使用除法、模运算、\n * 乘法、任何条件语句(if 或者 ?:)、任何比较运算符(例如 <、>或==)或任何循环。\n * "
},
{
"path": "exercise/ex2-58.c",
"chars": 297,
"preview": "/*\n * 练习题 2.58\n *\n * 编写过程 is_little_endian,当在小端法机器上编译和运行时返回 1,在大端法机器上\n * 编译运行时返回 0。这个程序应该可以运行在任何机器上,无论机器的字长是多少。\n */\nint "
},
{
"path": "exercise/ex2-59.c",
"chars": 208,
"preview": "/*\n * 练习题 2.59\n *\n * 编写一个 C 表达式,使它生成一个字,由 x 的最低有效字节和 y 中剩下的字节组成。\n * 对于运算数 x=0x89ABCDEF 和 y=0x76543210,就得到 0x765432EF。\n *"
},
{
"path": "exercise/ex2-60.c",
"chars": 731,
"preview": "/*\n * 练习题 2.60\n *\n * 假设我们将一个 w 位的字中的字节从 0(最低位)到 w/8-1(最高位)编号。写出下面\n * C 函数的代码,它会返回一个无符号值,其中参数 x 的字节 i 被替换成字节 b:\n *\n * uns"
},
{
"path": "exercise/ex2-61.c",
"chars": 1703,
"preview": "/*\n * 练习题 2.61\n *\n * 写一个 C 表达式,在下列描述的条件下产生 1,而在其他情况下得到 0。假设 x 是\n * int 类型。\n *\n * A. x 的任何位都等于 1\n * B. x 的任何位都等于 0\n * C. "
},
{
"path": "exercise/ex2-62.c",
"chars": 264,
"preview": "/*\n * 练习题 2.62\n *\n * 编写一个函数 int_shifts_are_logical(),在对 int 类型的数使用算术右移的机器上运\n * 行时,这个函数生成 1,而其他情况下生成 0。你的代码应该可以运行在任何字长的机器"
},
{
"path": "exercise/ex2-63.c",
"chars": 802,
"preview": "/*\n * 练习题 2.63\n *\n * 将下面的 C 函数代码补充完整。函数 srl 用算术右移(由值 xsra 给出)来完成逻辑右\n * 移,后面的其他操作不包括右移或者除法。函数 sra 用逻辑右移(由值 xsrl 给出)来\n * 完"
},
{
"path": "exercise/ex2-64.c",
"chars": 254,
"preview": "/*\n * 写出代码实现如下函数:\n *\n * Return 1 when any even bit of x equals 1; 0 otherwise. Assume w=32\n *\n * int any_even_o"
},
{
"path": "exercise/ex2-65.c",
"chars": 923,
"preview": "/*\n * 练习题 2.65\n *\n * Return 1 when x contains an even number of 1s; 0 otherwise.\n * Assume w=32\n *\n * 解决这个问题的关键是,我们利用了异或"
},
{
"path": "exercise/ex2-66.c",
"chars": 718,
"preview": "/*\n * 练习题 2.66\n *\n * Generate mask indicating leftmost 1 in x. Assume w=32.\n * For example, 0xFF00 -> 0x8000, and 0x600"
},
{
"path": "exercise/ex2-67.c",
"chars": 1392,
"preview": "/*\n * 练习题 2.67\n *\n * 给你一个任务,编写一个过程 int_size_is_32(),当在一个 int 是 32 位的机器上\n * 运行时,该程序产生 1,而其他情况则产生 0。不允许使用 sizeof 运算符。下面是\n "
},
{
"path": "exercise/ex2-68.c",
"chars": 443,
"preview": "/*\n * 练习题 2.68\n *\n * 写出具有如下原型的函数的代码\n *\n * Make with least signficant n bits set to 1\n * Example: n = 6 --> 0x3f, n = 17 "
},
{
"path": "exercise/ex2-69.c",
"chars": 353,
"preview": "/*\n * 练习题 2.69\n *\n * Do rotating right shift. Assume 0 <= n < w\n * Example when x = 0x12345678 and w=32:\n * n=4 -> "
},
{
"path": "exercise/ex2-7.c",
"chars": 305,
"preview": "/*\n * 编译方法:\n * $ cc ex2-7.c ../show-bytes.c\n */\n\n#include <stdio.h>\n#include <string.h>\n\ntypedef unsigned char *byte"
},
{
"path": "exercise/ex2-70.c",
"chars": 666,
"preview": "/*\n * 练习题 2.70\n *\n * 写出具有如下原型的函数的代码:\n *\n * Return 1 when x can be represented as an n-bit, 2's complement\n * number; 0 o"
},
{
"path": "exercise/ex2-71.c",
"chars": 914,
"preview": "/*\n * 练习题 2.71\n *\n * 你刚刚开始在一家公司工作,他们要实现一组过程来操作一个数据结构,要将 4 个有\n * 符号字节封装成一个 32 位 unsigned。一个字中的字节从 0(最低有效字节)编号到\n * 3(最高有效字"
},
{
"path": "exercise/ex2-72.c",
"chars": 872,
"preview": "/*\n *\n * 给你一个任务,写一个函数,将整数 val 复制到缓冲区 buf 中,但是只有缓冲区\n * buf 中,但是只有当缓冲区中有足够可用的空间时,才执行复制。\n *\n * 你写的代码如下:\n *\n * // Copy integ"
},
{
"path": "exercise/ex2-73.c",
"chars": 1209,
"preview": "/*\n * 练习题 2.73\n *\n * Addition that saturates to TMin or TMax\n *\n * 通正常的补码溢出的方式不同,当正溢出时,saturating_add 返回 TMax,负溢出时,返\n * "
},
{
"path": "exercise/ex2-74.c",
"chars": 547,
"preview": "/*\n * 练习题 2.74\n *\n * 写出具有如下原型的函数的代码:\n *\n * // Determine whether subtracting arguments will cause overflow\n * int tsub_ov"
},
{
"path": "exercise/ex2-75.c",
"chars": 758,
"preview": "/*\n * 家庭作业 2.75\n *\n * 假设我们想要计算 x·y 的完整的 2w 位表示,其中,x 和 y 都是无符号数,并且运\n * 行在数据类型 unsigned 是 w 位的机器上。乘积的低 w 位能够用表达式 x·y 计算,\n "
},
{
"path": "exercise/ex2-76.c",
"chars": 748,
"preview": "/*\n * 练习题 2.76\n *\n * 假设我们有一个任务:生成一段代码,将整数变量 x 乘以不同的常数因子 K。为了提高\n * 效率,我们想只使用 +、- 和 << 运算。对于下列的 K 的值,写出执行乘法运算的C 表\n * 达式,每个"
},
{
"path": "exercise/ex2-77.c",
"chars": 594,
"preview": "/*\n * 家庭作业 2.77\n *\n * 写出具有如下原型的函数的代码:\n *\n * // Divide by power of two. Assume 0 <= k < w-1\n * int divide_power2(int x, "
},
{
"path": "exercise/ex2-78.c",
"chars": 287,
"preview": "/*\n * 家庭作业 2.78\n *\n * 写出函数 mul5div8 的代码,对于整数参数 x,计算 5*x/8,但是要遵循位级整数编\n * 码规则。你的代码计算 5*x 也会产生溢出。\n*/\n\n#include <limits.h>\n\n"
},
{
"path": "exercise/ex2-79.c",
"chars": 1285,
"preview": "/*\n * 家庭作业 2.79\n *\n * 写出函数 fiveeighths 的代码,对于整数参数 x,计算 5/8x 的值,向零舍入。它不会\n * 溢出。函数应该遵循整数位级编码规则。\n */\n\n#include <limits.h>\n\n"
},
{
"path": "exercise/ex2-80.c",
"chars": 431,
"preview": "/*\n * 家庭作业 2.80\n *\n * 编写 C 表达式产生如下位模式,其中 a^n 表示符号 a 重复 n 次。假设一个 w 位的\n * 数据类型。你的代码可以包含对参数 m 和 n 的引用,它们分别表示 m 和 n 的值,但\n * "
},
{
"path": "exercise/ex2-81.c",
"chars": 2382,
"preview": "/*\n * 练习题 2.81\n *\n * 我们在一个 int 类型值为 32 位的机器上运行程序。这些值以补码形式表示,而且它们\n * 都是算术右移的。unsigned 类型的值也是 32 位的。\n *\n * 我们产生随机数 x 和 y,并"
},
{
"path": "exercise/ex2-82.txt",
"chars": 414,
"preview": "A. 对于串 Y,如果我们将小数点右移 k 位,得到的数字将是无穷串的开始 k 位。如果我们将\n Y 右移 2k 位,得到的数字将是无穷串的 k+1~2k 位。依次类推,我们可以得到下列的公式:\n\n S = Y * (2^-"
},
{
"path": "exercise/ex2-83.c",
"chars": 2320,
"preview": "/*\n * 家庭作业 2.83\n *\n * 填写下列程序的返回值,这个程序是测试它的第一个参数是否大于或者等于第二个参\n * 数。假定函数 f2u 返回一个无符号 32 位数字,其位表示与它的浮点参数相同。你可\n * 以假设两个参数都不是 "
},
{
"path": "exercise/ex2-84.txt",
"chars": 632,
"preview": "================================================================================\n给定一个浮点格式,有 k 位指数和 n 位小数,对于小列数,写出阶码 E、尾数"
},
{
"path": "exercise/ex2-85.txt",
"chars": 278,
"preview": "================================================================================\n家庭作业 2.85 的解答,题目请看 00-topic.txt\n======="
},
{
"path": "exercise/ex2-86.txt",
"chars": 378,
"preview": "================================================================================\n家庭作业 2.86 的解答,题目请看 00-topic.txt\n======="
},
{
"path": "exercise/ex2-87.txt",
"chars": 435,
"preview": "================================================================================\n家庭作业 2.87 的解答,题目请看 00-topic.txt\n======="
},
{
"path": "exercise/ex2-88.txt",
"chars": 267,
"preview": "================================================================================\n家庭作业 2.88 的解答,题目请看 00-topic.txt\n======="
},
{
"path": "exercise/ex2-89.c",
"chars": 1555,
"preview": "/*\n * 家庭作业 2.89\n *\n * 分配给你一个任务,编写一个 C 函数来计算 2^x 的浮点表示。你意识到完成这个任务的\n * 最好方法是直接创建结果的 IEEE 单精度表示。当 x 太小时,你的程序将返回0.0。当\n * x 太"
},
{
"path": "exercise/ex2-90.txt",
"chars": 751,
"preview": "================================================================================\n大约在公元前 250 年,希腊数学家阿基米德证明了 223/71 < PI <"
},
{
"path": "exercise/ex2-91.c",
"chars": 1655,
"preview": "/*\n * 家庭作业 2.91\n * mofaph@gmail.com\n *\n * 遵循位级浮点编码规则,实现具有如下原型的函数:\n *\n * // Compute |f|. If f is NaN, then return f.\n * "
},
{
"path": "exercise/ex2-92.c",
"chars": 628,
"preview": "/*\n * 家庭作业 2.92\n * mofaph@gmail.com\n *\n * 遵循位级浮点编码规则,实现具有如下原型的函数:\n *\n * // Compute -f. If f is Nan, then return f.\n * f"
},
{
"path": "exercise/ex2-93.c",
"chars": 1472,
"preview": "/*\n * 家庭作业 2.93\n * mofaph@gmail.com\n *\n * 遵循位级浮点编码规则,实现具有如下原型的函数:\n *\n * // Compute 0.5*f. If f is NaN, then return f.\n "
},
{
"path": "exercise/ex2-94.c",
"chars": 1036,
"preview": "/*\n * 家庭作业 2.94\n * mofaph@gmail.com\n *\n * 遵循位级浮点编码规则,实现具有如下原型的函数:\n *\n * // Compute 2*f. If f is NaN, then return f.\n * "
},
{
"path": "exercise/ex2-95.c",
"chars": 1681,
"preview": "/*\n * 家庭作业 2.95\n * mofaph@gmail.com\n *\n * 遵循位级浮点编码规则,实现具有如下原型的函数:\n *\n * // Compute (float) i\n * float_bits float_i2f(int"
},
{
"path": "exercise/ex2-96.c",
"chars": 1641,
"preview": "/*\n * 家庭作业 2.96\n * mofaph@gmail.com\n *\n * 遵循位级浮点编码规则,实现具有如下原型的函数:\n *\n * // Compute (int) f.\n * // If conversion causes o"
},
{
"path": "exercise/ex3-19.c",
"chars": 1024,
"preview": "/*\n * 练习题 3.19\n *\n * A. 用一个 32 位 int 表示 n!,最大的 n 的值是多少?\n * B. 如果用一个 64 位 long long int 表示,最大的 n 的值是多少?\n */\n\n/*\n * Return"
},
{
"path": "exercise/ex3-34.c",
"chars": 316,
"preview": "/*\n * 练习题 3.34\n */\n\nint rfun(unsigned x)\n{\n if (!x)\n return 0;\n unsigned nx = x >> 1;\n "
},
{
"path": "exercise/ex3-54.c",
"chars": 120,
"preview": "/*\n * 家庭作业 3.54\n */\n\nint decode2(int x, int y, int z)\n{\n int t = (z - y) & 0x7FFF;\n return (x ^ t) * t;\n}\n"
},
{
"path": "exercise/ex3-55.asm",
"chars": 1428,
"preview": " ;; 3.55\n\n ;; 在完成这道练习的过程中,因为没有考虑到 x * y 会发生隐式类型转换。\n ;; 也就是,y 从 int 类型转换为 long long 类型。这种转换是隐式进行的。\n "
},
{
"path": "exercise/ex3-56.txt",
"chars": 537,
"preview": "====\n3.56\n====\n\nA. esi: x\n ebx: n\n edi: result\n edx: mask\n\nB. result: 0x55555555\n mask: 0x80000000\n\nC. mask !="
},
{
"path": "exercise/ex3-57.c",
"chars": 236,
"preview": "/*\n * 3.57\n *\n * 参考链接:\n *\n * http://book.douban.com/annotation/20427266/\n */\n\n/*\n * 在条件传送中,既然不能对数值为 0 的地址取值。通过思维转换,那么就取数"
},
{
"path": "exercise/ex3-58.c",
"chars": 772,
"preview": "/*\n * 3.58\n */\n\n/* Enumberated type creates set of constants numbered 0 and upward */\ntypedef enum {\n MODE_A,\n "
},
{
"path": "exercise/ex3-59.c",
"chars": 474,
"preview": "/*\n * 3.59\n */\nint switch_prob(int x, int n)\n{\n int result = x;\n\n switch (n) {\n case 42:\n case 40:\n "
},
{
"path": "exercise/ex3-60.txt",
"chars": 72,
"preview": "3.60\n\nA. &A[i][j][k] = X_D + L(S·L·i + T·j + k)\nB. R = 44, S = 7, T = 9\n"
},
{
"path": "exercise/ex3-61.c",
"chars": 445,
"preview": "/*\n * 3.61\n *\n * $ gcc -O2 -S ex3-61.c # 这样就不会使循环的值溢出到存储器了\n */\n\n/* Compute i,k of variable matrix product */\nint var_pro"
},
{
"path": "exercise/ex3-62.c",
"chars": 380,
"preview": "/*\n * 3.62\n */\n\n/*\n * A. M=16\n * B. i: edi, j: ecx\n * C. 如下所示\n */\nvoid transpose(int M, int A[M][M])\n{\n int i, j;"
},
{
"path": "exercise/ex3-63.txt",
"chars": 44,
"preview": "3.63\n\n#define E1(n) 3*n\n#define E2(n) 2*n-1\n"
},
{
"path": "exercise/ex3-64.txt",
"chars": 165,
"preview": "3.64\n\nA. eax: result, ebx: s1.v, edx: s1.p\nB. ebp-4: s1, ebp-8: s2, ebp-12: y, ebp-16: &x, ebp-20: s2\nC. 将结构的各位成员,按从高到低地"
},
{
"path": "exercise/ex3-65.txt",
"chars": 91,
"preview": "3.65\n\nA=2, B=8\n\n将 x 看作是有 A 个元素的数组,每个元素是一个含有 B 个元素的数组。由于需要每个元\n素对齐,B 数组需要 16 个字节,所以 16 字节对齐。\n"
},
{
"path": "exercise/ex3-66.txt",
"chars": 533,
"preview": "3.66\n\nA. CNT=7\nB. struct a_struct { int idx; int x[6]; };\n\n这里要注意的是,生成的汇编代码中使用了一个技巧。这样就不容易看出来地址间的运算关\n系了:\n\n 10 add 0x4("
},
{
"path": "exercise/ex3-67.c",
"chars": 376,
"preview": "/*\n * 3.67\n *\n * mofaph@gmail.com\n */\n\nunion ele {\n struct {\n int *p;\n int x;\n "
},
{
"path": "exercise/ex3-68.c",
"chars": 542,
"preview": "/*\n * 3.68\n *\n * mofaph@gmail.com\n */\n\n#include <stdio.h>\n\n#define MAX_INPUT 5 /* 以小一点的数字,使问题可以方便地出现(如果有的话) "
},
{
"path": "exercise/ex3-69.c",
"chars": 619,
"preview": "/*\n * 3.69\n *\n * $ cc -m64 -S ex3-69.c # 使用 -m64 生成 64 位代码\n *\n * mofaph@gmail.com\n */\n\ntypedef struct ELE *tree_ptr;\n\nst"
},
{
"path": "exercise/ex3-70.c",
"chars": 542,
"preview": "/*\n * 3.70\n *\n * $ gcc -m64 -S ex3-70.c # 生成 64 位的汇编代码\n *\n * mofaph@gmail.com\n */\n\ntypedef struct ELE *tree_ptr;\n\nstruct"
},
{
"path": "exercise/ex7-10.txt",
"chars": 254,
"preview": "7.10\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\nA. gcc -static "
},
{
"path": "exercise/ex7-11.txt",
"chars": 110,
"preview": "7.11\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\n.bss\n"
},
{
"path": "exercise/ex7-12.txt",
"chars": 747,
"preview": "7.12\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\n |---------"
},
{
"path": "exercise/ex7-13.txt",
"chars": 299,
"preview": "7.13\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\nA. 0xc R_386_P"
},
{
"path": "exercise/ex7-14.txt",
"chars": 485,
"preview": "7.14\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\nA. .text:\n "
},
{
"path": "exercise/ex7-15.txt",
"chars": 456,
"preview": "7.15\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\nA. $ libs=$(fin"
},
{
"path": "exercise/ex7-6.txt",
"chars": 1161,
"preview": "7.6\n\n|-------+----------------------+----------+----------------+-------|\n| 符号 | .swap.o.symtab条目? | 符号类型 | 定义符号的模块 | 节"
},
{
"path": "exercise/ex7-7.c",
"chars": 256,
"preview": "/*\n * 7.7\n *\n * mofaph@gmail.com\n */\n\n/*\n * Solution 1\n */\n\nint x;\n\nvoid f()\n{\n x = 15213;\n}\n\n/*\n * Solution 2\n *"
},
{
"path": "exercise/ex7-8.txt",
"chars": 219,
"preview": "7.8\n\nmofaph@gmail.com\n\nA.\n\na) REF(main.1) --> DEF(main.1)\nb) REF(main.2) --> DEF(main.2)\n\nB.\n\na) REF(x.1) --> DEF(x.UNKN"
},
{
"path": "exercise/ex7-9.txt",
"chars": 695,
"preview": "7.9\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\n这道习题我没能解决,因为我没有注"
},
{
"path": "exercise/ex8-10.txt",
"chars": 183,
"preview": "8.10\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\nA. 调用一次,返回两次。\n\n"
},
{
"path": "exercise/ex8-11.c",
"chars": 628,
"preview": "/*\n * 8.11\n *\n * 这个程序会输出多少个“hello”输出行?\n *\n * unix> gcc -I../common ex8-11.c ../common/csapp.c -lpthread\n * #4\n */\n\n#incl"
},
{
"path": "exercise/ex8-12.c",
"chars": 301,
"preview": "/*\n * 8.12\n *\n * 这个程序会输出多少个“hello”输出行?\n *\n * unix> gcc -I../common ex8-12.c ../common/csapp.c -lpthread\n * #8\n */\n\n#incl"
},
{
"path": "exercise/ex8-13.c",
"chars": 354,
"preview": "/*\n * 8.13\n *\n * 下面程序的一种可能的输出是什么?\n *\n * unix> gcc -I../common ex8-13.c ../common/csapp.c -lpthread\n *\n * 父进程先运行:\n * 4\n *"
},
{
"path": "exercise/ex8-14.c",
"chars": 451,
"preview": "/*\n * 8.14\n *\n * 下面这个程序会输出多少个“hello”输出行?\n *\n * unix> gcc -I../common ex8-14.c ../common/csapp.c -lpthread\n *\n * 第一个 Fork"
},
{
"path": "exercise/ex8-15.c",
"chars": 440,
"preview": "/*\n * 8.15\n *\n * 下面这个程序会输出多少个“hello”输出行?\n *\n * unix> gcc -I../common ex8-15.c ../common/csapp.c -lpthread\n *\n * 第一个 Fork"
},
{
"path": "exercise/ex8-16.c",
"chars": 354,
"preview": "/*\n * 8.16\n *\n * unix> gcc -I../common ex8-16.c ../common/csapp.c -lpthread\n * counter = 2\n */\n\n#include \"csapp.h\"\n\nint "
},
{
"path": "exercise/ex8-17.txt",
"chars": 418,
"preview": "8.17\n\nmofaph@gmail.com\n--------------------------------------------------------------------------------\n\nfork() 失败:\n "
}
]
// ... and 132 more files (download for full content)
About this extraction
This page contains the full source code of the mofaph/csapp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 332 files (941.5 KB), approximately 277.4k tokens, and a symbol index with 723 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.