深入理解计算机系统英文版(从672页开始翻译-要做实验没办法)

12.8 Putting it Together: TheTINYWeb Server

We will conclude our discussion of network programming by developing a small but functioning Web servercalled TINY. TINYis an interesting program. It combines many of the ideas that we have learned about concurrency, Unix I/O, the sockets interface, and HTTP in only 250 lines of code. While it lacks the functionality, robustness, and security of a real server, it is powerful enough to serve both static and dynamic content to real Web browsers. We encourage you to study it and implement it yourself. It is quite exciting (even for the authors!) to point a real browser at your own server and watch it display a complicated Web

page with text and graphics.

我们将通过开发一个叫做tiny的小但是起作用的web服务,来理解网络编程。Tiny是一个有趣的程序。它包含了许多我们已经一致了解的思路,Unix I/Osockets接口,还有HTTP,这些包含在仅仅250行的代码中。尽管它缺乏一个真正的服务的实用性,健壮性,和安全性,它仍然足够给力,给真正的web浏览器提供静态和动态的内容服务。我们鼓励你自己学习它,运用它。它足够令人兴奋(即使对于作者来说!)让浏览器指向你自己的服务,并且观看它展示一个复杂的包含文本和图片的网页。

 

code/net/tiny/cgi-bin/adder.c

1#include "csapp.h"

2

3int main(void) {

4char *buf, *p;

5char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];

6int n1=0, n2=0;

7

8/* extract the two arguments */

9if ((buf = getenv("QUERY_STRING")) != NULL) {

10p = strchr(buf, ’&’);

11*p = ’/0’;

12strcpy(arg1, buf);

13strcpy(arg2, p+1);

14n1 = atoi(arg1);

15n2 = atoi(arg2);

16}

17

18/* make the response body */

19sprintf(content, "Welcome to add.com: ");

20sprintf(content, "%sTHE Internet addition portal./r/n<p>", content);

21sprintf(content, "%sThe answer is: %d + %d = %d/r/n<p>",

22content, n1, n2, n1 + n2);

23sprintf(content, "%sThanks for visiting!/r/n", content);

24

25/* generate the HTTP response */

26printf("Content-length: %d/r/n", strlen(content));

27printf("Content-type: text/html/r/n/r/n");

28printf("%s", content);

29fflush(stdout);

30exit(0);

31}

 

1unix> telnet kittyhawk.cmcl.cs.cmu.edu 8000Client: open connection

2Trying 128.2.194.242...

3Connected to kittyhawk.cmcl.cs.cmu.edu.

4Escape character is ’ˆ]’.

5GET /cgi-bin/adder?15000&213 HTTP/1.0Client: request line

6 Client: empty line terminates headers

7HTTP/1.0 200 OK Server: response line

8Server: Tiny Web Server Server: identify server

9Content-length: 115 Adder: expect 115 bytes in response body

10Content-type: text/html Adder: expect HTML in response body

11 Adder: empty line terminates headers

12Welcome to add.com: THE Internet addition portal.Adder: first HTML line

13<p>The answer is: 15000 + 213 = 15213Adder: second HTML line in response body

14<p>Thanks for visiting! Adder: third HTML line in response body

15Connection closed by foreign host.Server: closes connection

16unix> Client: closes connection and terminates

Figure 12.45:An HTTP transaction that serves dynamic HTML content

 

TheTINYmain Routine

Figure 12.46 shows TINY’s main routine. TINY is an iterative server that listens for connection requests on the port that is passed in the command line. After opening a listening socket (line 28) by calling the open_listenfdfunction from Figure 12.46, TINYexecutes the typical infinite server loop, repeatedly accepting a connection request (line 31) and performing a transaction (line 32).

Figure 12.46显示了tiny的主函数。Tiny是一个持续的服务,监听来自命令行设置的端口的请求。通过调用来自Figure 12.4open_listenfd函数来打开一个正在监听的socket (28)Tiny执行了不间断的server循环,不停的接受一个个连接请求,并且实现交互。

 

Thedoit Function

Thedoit function in Figure 12.47 handles one HTTP transaction. First, we read and parse the request line(lines 9-10). Notice that we are using the robust readlinefunction from Figure 12.16 to read the request line.

Figure 12.47doit函数处理了一个HTTP交互。首先,我们读取并且转换这个请求行(request line)。请注意,我们一直使用健壮的来自Figure 12.16readline函数来读取request line

TINYonly supports the GET method. If the client requests another method (such as POST), we send it an error message and return to the main routine (lines 11-15), which then closes the connection and awaits the next connection request. Otherwise, we read and (as we shall see) ignore any request headers (line 16).

Tiny仅仅支持GET方法。如果客户端使用其他方法(例如POST)请求服务,我们将发送一个错误消息,并且等待下一次连接请求。另外,我们忽视并且(我们应该看到)忽视任何的request headers

Next, we parse the URI into a filename and a possibly empty CGI argument string, and we set a flag that indicates whether the request is for static or dynamic content (line 19). If the file does not exist on disk, we immediately send an error message to the client and return (lines 20-24).

另外,我们将URI(统一资源标识符)转换成一个文件名和一个可能的空的CGI参数字符串,而且,我们会设置一个标志,它指出了这个请求是为了静态的还是动态的内容。如果这个文件在磁盘上不存在,我们立刻会发送一个错误消息给客户端并且返回(l20-24).

Finally, if the request is for static content (lines 26), we verify that the file is a regular file (i.e., not a directory file or a FIFO) and that we have read permission (line 27). If so, we serve the static content (line 32) to the client. Similarly, if the request is for dynamic content (line 34), we verify that the file is executable (line 35), and if so we go ahead and serve the dynamic content (line 40).

最后,如果这个请求是为了静态内容(26行),我们将核实这个文件是一个正常的文件(不是一个路径文件或者一个FIFO,等等)而且我们有读取权限。如果都符合了,我们给客户端提供静态内容服务。同样的,如果这个请求是为了动态内容(34行),我们将核实这个文件是可执行的,而且符合的话,我们会开始提供动态内容服务。

 

1/*

2* tiny.c - A simple HTTP/1.0 Web server that uses the GET method

3* to serve static and dynamic content.

4*/

5#include "csapp.h"

6

7void doit(int fd);

8void read_requesthdrs(int fd);

9int parse_uri(char *uri, char *filename, char *cgiargs);

10void serve_static(int fd, char *filename, int filesize);

11void get_filetype(char *filename, char *filetype);

12void serve_dynamic(int fd, char *filename, char *cgiargs);

13void clienterror(int fd, char *cause, char *errnum,

14char *shortmsg, char *longmsg);

15

16int main(int argc, char **argv)

17{

18int listenfd, connfd, port, clientlen;

19struct sockaddr_in clientaddr;

20

21/* check command line args */

22if (argc != 2) {

23fprintf(stderr, "usage: %s <port>/n", argv[0]);

24exit(1);

25}

26port = atoi(argv[1]);

27

28listenfd = open_listenfd(port);

29while (1) {

30clientlen = sizeof(clientaddr);

31connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);

32doit(connfd);

33Close(connfd);

34}

35}

Figure 12.46:The TINY Web server

 

1void doit(int fd)

2{

3int is_static;

4struct stat sbuf;

5char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];

6char filename[MAXLINE], cgiargs[MAXLINE];

7

8/* read request line and headers */

9Readline(fd, buf, MAXLINE);

10sscanf(buf, "%s %s %s/n", method, uri, version);

11if (strcasecmp(method, "GET")) {

12clienterror(fd, method, "501", "Not Implemented",

13"Tiny does not implement this method");

14return;

15}

16read_requesthdrs(fd);

17

18/* parse URI from GET request */

19is_static = parse_uri(uri, filename, cgiargs);

20if (stat(filename, &sbuf) < 0) {

21clienterror(fd, filename, "404", "Not found",

22"Tiny couldn’t find this file");

23return;

24}

25

26if (is_static) { /* serve static content */

27if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) {

28clienterror(fd, filename, "403", "Forbidden",

29"Tiny couldn’t read the file");

30return;

31}

32serve_static(fd, filename, sbuf.st_size);

33}

34else { /* serve dynamic content */

35if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) {

36clienterror(fd, filename, "403", "Forbidden",

37"Tiny couldn’t run the CGI program");

38return;

39}

40serve_dynamic(fd, filename, cgiargs);

41}

42}

code/net/tiny/tiny.c

Figure 12.47: TINYdoit: Handles one HTTP transaction.

 

TheclienterrorFunction

TINYlacks many of the robustness features of a real server. However it does check for some obvious errors and reports them to the client. Theclienterror function in Figure 12.48 sends an HTTP response to the client with the appropriate status code and status message in the response line, along with an HTML file in the response body that explains the error to the browser’s user.

Tiny缺乏一个真正的服务的很多方面的健壮性。即使这样,它也检查了许多明显的错误,并且将它们报告给客户端。这个Figure 12.48 clienterror函数发送了一个HTTP response给客户端,包含了合适的状态码和状态消息在response line中,与response body中的html文件一起向浏览器使用者解释了一个错误。

code/net/tiny/tiny.c

1void clienterror(int fd, char *cause, char *errnum,

2char *shortmsg, char *longmsg)

3{

4char buf[MAXLINE], body[MAXBUF];

5

6/* build the HTTP response body */

7sprintf(body, "<html><title>Tiny Error</title>");

8sprintf(body, "%s<body bgcolor=""ffffff"">/r/n", body);

9sprintf(body, "%s%s: %s/r/n", body, errnum, shortmsg);

10sprintf(body, "%s<p>%s: %s/r/n", body, longmsg, cause);

11sprintf(body, "%s<hr><em>The Tiny Web server</em>/r/n", body);

12

13/* print the HTTP response */

14sprintf(buf, "HTTP/1.0 %s %s/r/n", errnum, shortmsg);

15Writen(fd, buf, strlen(buf));

16sprintf(buf, "Content-type: text/html/r/n");

17Writen(fd, buf, strlen(buf));

18sprintf(buf, "Content-length: %d/r/n/r/n", strlen(body));

19Writen(fd, buf, strlen(buf));

20Writen(fd, body, strlen(body));

21}

code/net/tiny/tiny.c

Figure 12.48: TINYclienterror: Sends an error message to the client.

 

Recall that an HTML response should indicate the size and type the content in the body. Thus, we have opted to build the HTML content as a single string (lines 7-11) so that we can easily determine its size (line 18). Also, notice that we are using the robustwriten function from Figure 12.15 for all output.

回想一下,一个HTML回复应该指明body中内容的大小和类型。因此,我们选择创建一个HTML content在一个单独的字符串中(7-11行),这样我们能够容易的指导它的大小(18行)。同时,注意到这个,我们一直为所有的输出使用健壮的writen方法

 

 

Theread requesthdrsFunction

TINYdoes not use any of the information in the request headers. It simply reads and ignores them by calling theread_requesthdrs function in Figure 12.49. Notice that the empty text line that terminates the request headers consists of a carriage return and line feed pair, which we check for in line 6.

Tiny没有在request headers中使用任何信息。它通过调用read_requesthdrs函数简单的读取并且忽视它们(Figure 12.49)。注意到,由回车和换行字符组成的空行终结了request headers部分。

658 CHAPTER 12. NETWORK PROGRAMMING

code/net/tiny/tiny.c

1void read_requesthdrs(int fd)

2{

3char buf[MAXLINE];

4

5Readline(fd, buf, MAXLINE);

6while(strcmp(buf, "/r/n"))

7Readline(fd, buf, MAXLINE);

8return;

9}

code/net/tiny/tiny.c

Figure 12.49: TINYread requesthdrs: Reads and ignores request headers.

 

 

Theparse uriFunction

TINYassumes that the home directory for static content is the current Unix directory’.’, and that the home directory for executables is./cgi-bin. Any URI that contains the stringcgi-bin is assumed to denote a request for dynamic content. The default file name is./home.html.

Tiny假设静态内容的主路径是Unix当前路径’.’,而可执行文件的主路径是./cgi-bin。任何包含cgi-bin字符串的URI都会被认为是对动态内容的请求。默认的文件名是./home.html.

Theparse_uri function in Figure 12.50 implements these policies. It parses the URI into a filename and an optional CGI argument string. If the request is for static content (line 5) we clear the CGI argument string (line 6), and then convert the URI into a relative Unix pathname such as./index.html (lines 7-8). If the URI ends with a’/’ character (line 9), then we append the default file name (lines 9). On the other hand, if the request is for dynamic content (line 13), we extract any CGI arguments (line 14-20) and convert the

remaining portion of the URI to a relative Unix file name (lines 21-22).

Figure 12.50parse_uri函数实现了如下策略。它将URI转换成一个文件名,和一个可以选择的CGI参数字符串。如果请求是为了静态的内容(5行),我们清空CGI字符串(6行),然后将URI转换成一个相关的UNIX路径名,例如./index.html7-8行)。如果URI以字符’/’结束(9行),那么我们将加上默认的文件名(9行)。另一方面,如果请求是为了动态内容(13行),我们将提取CGI参数(14-20行),并且将URI剩余的部分转换成相关的Unix文件名(21-22行)。

 

Theserve staticFunction

TINYserves 4 different types of static content: HTML files, unformatted text files, and images encoded in GIF and JPG formats. These file types account for the majority of static content served over the Web.

Tiny提供了四个不同类型的静态文件:HTML文件,无格式文本文件,GIFJPG格式编码的图像文件。这些文件类型组成了在web上提供服务的主要的静态内容。

Theserve static function in Figure 12.51 sends an HTTP response whose body contains the contents of a local file. First, we determine the file type by inspecting the suffix in the filename (line 7), and then send the response line and response headers to the client (lines 6-12). Notice that we are using thewriten function from Figure 12.15 for all output on the descriptor. Notice also that a blank line terminates the headers (line 12).

Figure 12.51Serve_static函数发送了一个HTTP response,它的body包含了本地文件的内容。首先,我们通过查看文件名后缀(7行)检测文件类型,然后发送一个response line response headers给客户端(6-12行)。请注意,我们一直使用Figure 12.15writen函数来执行所有的输出。还要注意到,一个空行结束了headers

Next, we send the response body by copying the contents of the requested file to the connected descriptor fd (lines 15-19). The code here is somewhat subtle and needs to be studied carefully.

然后,我们发送response body通过复制所请求的文件的内容给连接描述符fd15-19行)。这儿的代码是充满玄机的,需要仔细学习。

Line 15 opensfilename for reading and gets its descriptor. In line 16, the Unixmmap function maps the requested file to a virtual memory area. Recall from our discussion ofmmap in Section 10.8 that the call tommap maps the firstfilesize bytes of filesrcfd to a private read-only area of virtual memory that starts at addresssrcp.

15行打开了文件filename来读取,并获得它的描述符。在第16行中,Unix mmap函数映射了所请求的文件到虚拟内存空间。记起我们曾在10.8章讨论过的mmap,调用mmap将文件srcfd的第一个filesize比特大小的内容映射到只读的开始于地址srcp的虚拟内存区域。

Once we have mapped the file to memory, we no longer need its descriptor, so we close the file (line 17).

一旦我们将文件映射到内存,我们不再需要它的描述符,这样我们就可以关闭文件(17行)。

 

12.8. PUTTING IT TOGETHER: THE TINY WEB SERVER 659

code/net/tiny/tiny.c

1int parse_uri(char *uri, char *filename, char *cgiargs)

2{

3char *ptr;

4

5if (!strstr(uri, "cgi-bin")) { /* static content */

6strcpy(cgiargs, "");

7strcpy(filename, ".");

8strcat(filename, uri);

9if (uri[strlen(uri)-1] == ’/’)

10strcat(filename, "home.html");

11return 1;

12}

13else { /* dynamic content */

14ptr = index(uri, ’?’);

15if (ptr) {

16strcpy(cgiargs, ptr+1);

17*ptr = ’/0’;

18}

19else

20strcpy(cgiargs, "");

21strcpy(filename, ".");

22strcat(filename, uri);

23return 0;

24}

25}

code/net/tiny/tiny.c

Figure 12.50: TINYparse uri: Parses an HTTP URI.

660 CHAPTER 12. NETWORK PROGRAMMING

code/net/tiny/tiny.c

1void serve_static(int fd, char *filename, int filesize)

2{

3int srcfd;

4char *srcp, filetype[MAXLINE], buf[MAXBUF];

5

6/* send response headers to client */

7get_filetype(filename, filetype);

8sprintf(buf, "HTTP/1.0 200 OK/r/n");

9sprintf(buf, "%sServer: Tiny Web Server/r/n", buf);

10sprintf(buf, "%sContent-length: %d/n", buf, filesize);

11sprintf(buf, "%sContent-type: %s/r/n/r/n", buf, filetype);

12Writen(fd, buf, strlen(buf));

13

14/* send response body to client */

15srcfd = Open(filename, O_RDONLY, 0);

16srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);

17Close(srcfd);

18Writen(fd, srcp, filesize);

19Munmap(srcp, filesize);

20}

21

22/*

23* get_filetype - derive file type from file name

24*/

25void get_filetype(char *filename, char *filetype)

26{

27if (strstr(filename, ".html"))

28strcpy(filetype, "text/html");

29else if (strstr(filename, ".gif"))

30strcpy(filetype, "image/gif");

31else if (strstr(filename, ".jpg"))

32strcpy(filetype, "image/jpg");

33else

34strcpy(filetype, "text/plain");

35}

code/net/tiny/tiny.c

Figure 12.51: TINYserve static: Serves static content to a client.

 

 

12.8. PUTTING IT TOGETHER: THE TINY WEB SERVER 661

Failing to do this would introduce a potentially fatal memory leak.

做这个失败的话,将会导致一个潜在的致命的内存溢出。

Line 18 performs the actual transfer of the file to the client. Thewriten function copies thefilesize bytes starting at locationsrcp (which of course is mapped to the requested file) to the client’s connected descriptor. Finally, line 19 frees the mapped virtual memory area. This is important to avoid a potentially fatal memory leak.

18行表现了文件到客户端实际的传输。Writen函数复制了开始于位置srcp(这个course代表了被请求的文件)的filesize比特的内容给客户的连接描述符。最后,第19行释放了映射的虚拟内存空间。这对于避免潜在的致命的内存溢出是至关重要的。

 

 

Theserve dynamicFunction

TINYserves any type of dynamic content by forking a child process, and then running a CGI program in the context of the child.

Tiny提供一些类型的动态内容,通过创建一个子进程,然后在子进程的内容中运行一个CGI程序。

Theserve dynamic function in Figure 12.52 begins by sending a response line indicating success to the client (lines 6-7), along with an informationalServer header (lines 8-9). The CGI program is responsible for sending the rest of the response. Notice that this is not as robust as we might wish, since it doesn’t allow for the possibility that the CGI program might encounter some error.

Figure 12.52Serve_dynamic函数通过发送一个指示成功的response line给客户开始(6-7行),和包含一些信息的server headers8-9行)。这个CGI程序对于发送剩下的response是重要的。请注意,这不是像我们希望的那样健壮,它不允许CGI程序出错的可能性。

code/net/tiny/tiny.c

1void serve_dynamic(int fd, char *filename, char *cgiargs)

2{

3char buf[MAXLINE];

4

5/* return first part of HTTP response */

6sprintf(buf, "HTTP/1.0 200 OK/r/n");

7Writen(fd, buf, strlen(buf));

8sprintf(buf, "Server: Tiny Web Server/r/n");

9Writen(fd, buf, strlen(buf));

10

11if (Fork() == 0) { /* child */

12/* real server would set all CGI vars here */

13setenv("QUERY_STRING", cgiargs, 1);

14Dup2(fd, STDOUT_FILENO); /* redirect output to client */

15Execve(filename, NULL, environ); /* run CGI program */

16}

17Wait(NULL); /* parent reaps child */

18}

code/net/tiny/tiny.c

Figure 12.52: TINYserve dynamic: Serves dynamic content to a client.

 

 

After sending the first part of the response, we fork a new child process (line 11). The child initializes the QUERY STRING environment variable with the CGI arguments from the request URI (line 13). Notice that a real server would set the other CGI environment variables here as well. For brevity, we have omitted this step.

发送了response的第一部分之后,我们创建了一个新的子进程(11行)。这个子进程用来自request URICGI参数初始化了QUERY STRING环境变量(13行)。请注意,一个真正的服务也会在这设置其他的CGI环境变量。简单的说,我们省略了这个步骤。

Next, the child redirects the child’s standard output to the connected file descriptor (line 14), and then loads and runs the CGI program (line 15). Since the CGI program runs in the context of the child, it has access to the same open descriptors and environment variables that existed before the call to theexecve function. Thus, everything that the CGI program writes to standard output goes directly to the client process, without any intervention from the parent process.

接下来,这个子进程重定向了子进程标准输出到连接的文件的描述符(14行)。然后装载并运行CGI程序(15行)。CGI程序运行在子进程的上下文环境后,在调用execve函数之前,它访问了相同的打开描述符和存在的环境变量。因此,CGI程序写到标准输出的所有东西都会定向到client进程中,父进程对此没有任何干涉。

Meanwhile, the parent blocks in a call towait, waiting to reap the child when it terminates (line 17).

同时,父进程被阻塞了只能等待,等待子进程结束时,重新运行(17行)。

Practice Problem 12.8:

A. Is the TINYdoit routine reentrant? Why or why not?

B. If not, how would you make it reentrant?

 

12.9 Summary

In this chapter we have learned some basic concepts about network applications. Network applications use the client-server model, where servers perform services on behalf of their clients. The Internet provides network applications with two key mechanisms: (1) A unique name for each Internet host, and (2) a mechanism for establishing a connection to a server running on any of those hosts. Clients and servers establish connections by using the sockets interface, and they communicate over these connections using standard Unix file I/O functions.

在本章中,我们学习了网络程序的一些基本概念。网络程序使用客户端-服务器模型,服务器为它们的客户端提供服务。因特网提供网络应用程序通过两个主要的途径:(1)每台因特网主机一个唯一的名字,(2)一种运行在所有主机上的与服务器建立连接的机制。客户端和服务端通过使用sockets接口建立连接,而且他们通过连接使用标准Unix文件I/O函数通信。

There are two basic design options for servers. An iterative server handles one request at a time. A concurrent server can handle multiple requests concurrently. We investigated two designs for concurrent servers, one that forks a new process for each request, the other that creates a new thread for each request. Other designs are possible, such as using the Unix select function to explicitly manage the concurrency, or avoiding the per-connection overhead by pre-forking a set of child processes to handle connection requests.

服务器有两个基本的设计选择。一个迭代的服务处理每个请求一次。一个并发的服务能同时处理多个请求。我们为并发的服务调查了两种设计,一种设计给每个请求创建一个新的进程,另一种给每个请求创建一个新的线程。其他的设计也是可能的,例如使用Unix select函数去明确的管理并发性,或者避免每个连接的管理费用,通过先创建一系列的子进程来处理连接请求。

Finally, we studied the design and implementation of a simple but functional Web server. In a few lines of code, it ties together many important systems concepts such as Unix I/O, memory mapping, concurrency, the sockets interface, and the HTTP protocol.

最后,我们学习了这些设计并实现一个简单但起作用的web服务。在很少的代码中,它包含了许多重要的系统概念,例如Unix I/O,内存映射,并发性,sockets接口,和HTTP协议。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
从程序员的视角,看计算机系统! 本书适用于那些想要写出更快、更可靠程序的程序员。通过掌握程序是如何映射到系统上,以及程序是如何执行的,读者能够更好的理解程序的行为为什么是这样的,以及效率低下是如何造成的。粗略来看,计算机系统包括处理器和存储器硬件、编译器、操作系统和网络互连环境。而通过程序员的视角,读者可以清晰地明白学习计算机系统的内部工作原理会对他们今后作为计算机科学研究者和工程师的工作有进一步的帮助。它还有助于为进一步学习计算机体系结构、操作系统、编译器和网络互连好准备。 本书的主要论题包括:数据表示、C程序的机器级表示、处理器结构,程序优化、存储器层次结构、链接、异常控制流、虚拟存储器和存储器管理、系统级I/O、网络编程和并发编程。书中所覆盖的内容主要是这些方面是如何影响应用和系统程序员的。例如,在讲述数据表示时,本书说明了用来表示数字的表示方法是有限的,它能够近似地表示整数和实数,但是这种表示方法是有限制的,程序员必须了解。在讲述高速缓存时,本书讨论了矩阵代码中的循环变量的顺序是如何影响程序的性能的。在讨论网络互连时,本书描述了并发服务器如何能有效地处理来自多个客户端的请求。 本书基于Intel兼容(IA32)机器,在Unix或者相关的操作系统(例如,Linux)上执行C程序。虽然书中包括了一些帮助读者将Java转化成C的提示,但是还是要求读者对C或者C++有一定的了解。 您可以通过本书的Web网站www.csapp.cs.cmu.edu获得完整的资料,包括实验和作业,授课笔记和代码示例。 本书英文版久负盛名,被众多专业人士称为“最伟大的计算机教材”之一,著名的美国卡内基梅隆大学计算机科学系一直将本书作为教材使用,程序员眼中的透彻讲述计算机系统的扛鼎之作。作者Randal E. Bryant是卡耐基梅隆大学的计算机科学系主任,ACM和IEEE双院士(Fellow),其研究成果多次获得ACM和IEEE颁发的大奖。   本书共分十三章,分别介绍了信息的表示和处理、程序的机器级表示、处理器体系结构、存储器层次结构、静态和动态链接、虚拟存储器、系统级I/O、网络编程和并发编程等精彩内容。其目的是解释计算机系统的所有本质概念,并向读者展示这些概念是如何实际地影响应用程序的正确性、性能和实用性。与其他主要针对系统构造人员的系统类书籍不同,这本书是写给程序员的,是从程序员的角度来描述的。本书为软件和硬件之间搭起了一个桥梁,它给出了一种帮助读者分别从硬件和软件的角度去理解一个程序及其行为的途径,这也填补了国内计算机系统教学中的一个空白。本书的最大优点是帮助读者理解概念,让读者很清楚地在脑海中构造一个层次型的计算机系统,从最低层数据在内存中的表示(如我们一直陌生的浮点数表示),到流水线指令的构成,到虚拟存储器,到编译系统,到动态加载库,到最后的用户应用。   本书提供了大量的例子和练习及部分答案。尤其值得一提的是,对于每一个基本概念都有相应的笔头或程序试验,加深读者的理解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值