《CSAPP》(第3版)答案(第十二章)(一)

《CSAPP》(第3版)答案(第十二章)(一)

P16

#include <stdio.h>
#include "csapp.h"
void *thread(void *vargp);
#define DEFAULT 4
int main(int argc, char* argv[]) {
  int N;
  if (argc > 2)
    unix_error("too many param");
  else if (argc == 2)
    N = atoi(argv[1]);
  else
    N = DEFAULT;
  int i;
  pthread_t tid;
  for (i = 0; i < N; i++) {
    Pthread_create(&tid, NULL, thread, NULL);
  }
  Pthread_exit(NULL);
}
void *thread(void *vargp) {
  printf("Hello, world\n");
  return NULL;
}

P17

  • A
    主线程没有等待另一个线程。
  • B
#include "csapp.h"

void *thread(void *vargp);
int main()
{
  pthread_t tid;
  
  Pthread_create(&tid, NULL, thread, NULL);
  // exit(0);
  Pthread_exit(NULL);
}

/* Thread routine */
void *thread(void *vargp)
{
  Sleep(1);
  printf("Hello, world!\n");
  return NULL;
}

P18

  • A
    不安全
  • B
    安全
  • C
    不安全

P19

#include <stdio.h>
#include "csapp.h"
#define WRITE_LIMIT 100000
#define PEOPLE 4
static int readtimes;
static int writetimes;
static int readcnt;
// if a reader is waiting when writing, reader first next round
static int reader_first;
sem_t mutex, w;
void *reader(void *vargp) {
  while (1) {
    P(&mutex);
    readcnt++;
    if (readcnt == 1)
      P(&w);
    V(&mutex);
    /* Critical section */
    readtimes++;
    reader_first = 0;
    /* Critical section */
    P(&mutex);
    readcnt--;
    if (readcnt == 0)
      V(&w);
    V(&mutex);
  }
}
void *writer(void *vargp) {
  while (1) {
    if (reader_first == 1)
      continue;
    P(&w);
    /* Critical section */
    writetimes++;
    if (writetimes == WRITE_LIMIT) {
      printf("read/write: %d/%d\n", readtimes, writetimes);
      exit(0);
    }
    /* Critical section */
    // if a reader is waiting, reader first next round
    if (readcnt == 1)
      reader_first = 1;
    V(&w);
  }
}
void init(void) {
  readcnt = 0;
  readtimes = 0;
  writetimes = 0;
  reader_first = 0;
  Sem_init(&w, 0, 1);
  Sem_init(&mutex, 0, 1);
}
int main(int argc, char* argv[]) {
  int i;
  pthread_t tid;
  init();
  for (i = 0; i < PEOPLE; i++)
    if (i%2 == 0)
      Pthread_create(&tid, NULL, reader, NULL);
    else
      Pthread_create(&tid, NULL, writer, NULL);
  Pthread_exit(NULL);
  exit(0);
}

P20

#include <stdio.h>
#include "csapp.h"

#define WRITE_LIMIT 100000
#define PEOPLE 20 // 10 reader and 10 writer
#define N 5

static int readtimes;
static int writetimes;
sem_t mutex;
sem_t readercnt;
void *reader(void *vargp) {
  while (1) {
    P(&readercnt);
    P(&mutex);
    readtimes++;
    V(&mutex);
    V(&readercnt);
  }
}

void *writer(void *vargp) {
  while (1) {
    P(&mutex);
    writetimes++;
    if (writetimes == WRITE_LIMIT) {
      printf("read/write: %d/%d\n", readtimes, writetimes);
      exit(0);
    }
    V(&mutex);
  }
}

void init(void) {
  readtimes = 0;
  writetimes = 0;
  Sem_init(&mutex, 0, 1);
  Sem_init(&readercnt, 0, N);
}

int main(int argc, char* argv[]) {
  int i;
  pthread_t tid;
  init();
  for (i = 0; i < PEOPLE; i++) {
    if (i%2 == 0)
      Pthread_create(&tid, NULL, reader, NULL);
    else
      Pthread_create(&tid, NULL, writer, NULL);
  }
  Pthread_exit(NULL);
  exit(0);
}

P21

#include <stdio.h>
#include "csapp.h"

#define WRITE_LIMIT 100000
#define PEOPLE 4
static int readtimes;
static int writetimes;
static int writecnt;
sem_t mutex, w;
static int number;

void *reader(void *vargp) {
  while (1) {
    // writer first
    if (writecnt > 0)
      continue;
    P(&w);
    /* Critical section */
    readtimes++;
    /* Critical section */
    V(&w);
  }
}

void *writer(void *vargp) {
  while (1) {
    P(&mutex);
    // one more writer wait to write
    writecnt++;
    V(&mutex);
    P(&w);
    /* Critical section */
    writetimes++;
    if (writetimes == WRITE_LIMIT) {
      printf("read/write: %d/%d\n", readtimes, writetimes);
      exit(0);
    }
    /* Critical section */
    V(&w);
    P(&mutex);
    // writer has written
    writecnt--;
    V(&mutex);
  }
}

void init(void) {
  writecnt = 0;
  readtimes = 0;
  writetimes = 0;
  Sem_init(&w, 0, 1);
  Sem_init(&mutex, 0, 1);
}

int main(int argc, char* argv[]) {
  int i;
  pthread_t tid;
  init();
  for (i = 0; i < PEOPLE; i++) {
    if (i%2 == 0)
      Pthread_create(&tid, NULL, reader, NULL);
    else
      Pthread_create(&tid, NULL, writer, NULL);
  }
  Pthread_exit(NULL);
  exit(0);
}

P22

#include "csapp.h"
/* read line from connfd and echo line to connfd */
int echo_line(int connfd);
void command(void);

int main(int argc, char **argv)
{
  int listenfd, connfd;
  socklen_t clientlen;
  struct sockaddr_storage clientaddr;
  fd_set read_set, ready_set;
  if (argc != 2) {
    fprintf(stderr, "usage: %s <port>\nuse port 5000 here\n", argv[0]);
    // default port 5000
    listenfd = Open_listenfd("5000");
  } else {
    listenfd = Open_listenfd(argv[1]);  //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
  // max n for select
  int n = listenfd+1;
  while (1) {
    ready_set = read_set;
    Select(n, &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
      clientlen = sizeof(struct sockaddr_storage);
      connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
      // listen to accepted io ports
      if (connfd+1 > FD_SETSIZE) {
        fprintf(stderr, "too many clients\n");
        Close(connfd);
      }
      n = n > connfd+1 ? n : connfd+1;
      FD_SET(connfd, &read_set);
    }
    // echo one line every time
    int fd;
    for (fd = listenfd+1; fd < n; fd++)
      if (FD_ISSET(fd, &ready_set))
        if (echo_line(fd) == -1) {
          Close(fd);
          FD_CLR(fd, &read_set);
        }
  }
}

void command(void) {
  char buf[MAXLINE];
  if (!Fgets(buf, MAXLINE, stdin))
    exit(0); /* EOF */
  printf("%s", buf); /* Process the input command */
}

int echo_line(int connfd) {
  ssize_t n;
  char buf[1];
  while ((n = Rio_readn(connfd, buf, 1)) > 0) {
    Rio_writen(connfd, buf, n);
    if (buf[0] = '\n')
      return 0;
  }
  return -1;
}

P23

@@ -1,7 +1,5 @@
 /*
- * 12.23.bug.c - A concurrent echo server based on select
- *
- * bug in this file
+ * 12.23.c - A concurrent echo server based on select
  */
 #include "csapp.h"
 
@@ -105,15 +103,21 @@
     /* 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) {
+      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 if (n == 0) {
+        Close(connfd); //line:conc:echoservers:closeconnfd
+        FD_CLR(connfd, &p->read_set); //line:conc:echoservers:beginremove
+        p->clientfd[i] = -1;          //line:conc:echoservers:endremove
+      }
+      /* n == -1, it's an error */
       else {
+        fprintf(stderr, "error in fd %d, close fd %d connection\n", connfd, connfd);
         Close(connfd); //line:conc:echoservers:closeconnfd
         FD_CLR(connfd, &p->read_set); //line:conc:echoservers:beginremove
         p->clientfd[i] = -1;          //line:conc:echoservers:endremove

P24

P25

thread safe?
Yes, mutex make it safe
reentrant? (我也不知道reentrant咋翻译)
No, share the same mutex

P26

#include <stdio.h>
#include "csapp.h"
/*
 * struct hostent *gethostbyname(const char *name)
 *
 * struct hostent {
 *   char *h_name;
 *   char **h_aliases;
 *   int  h_addrtype;
 *   int  h_length;
 *   char **h_addr_list;
 * }
 */
static sem_t mutex;
static void init_mutex(void) {
  Sem_init(&mutex, 0, 1);
}
struct hostent *gethostbyname_ts(const char *name, struct hostent *host) {
  struct hostent *sharehost;
  P(&mutex);
  sharehost = gethostbyname(name);
  
  // copy int
  host->h_addrtype = sharehost->h_addrtype;
  host->h_length = sharehost->h_length;
  
  // copy char *
  host->h_name = (char*)Malloc(strlen(sharehost->h_name));
  strcpy(host->h_name, sharehost->h_name);
  
  // copy char **
  int i;
  for (i = 0; sharehost->h_aliases[i] != NULL; i++) {}
  host->h_aliases = (char**)Malloc(sizeof(char*) * (i+1));
  for (i = 0; sharehost->h_aliases[i] != NULL; i++) {
    // copy every char *
    host->h_aliases[i] = (char*)Malloc(strlen(sharehost->h_aliases[i]));
    strcpy(host->h_aliases[i], sharehost->h_aliases[i]);
  }
  host->h_aliases[i] = NULL;
  for (i = 0; sharehost->h_addr_list[i] != NULL; i++) {}
  host->h_addr_list = (char**)Malloc(sizeof(char*) * (i+1));
  for (i = 0; sharehost->h_addr_list[i] != NULL; i++) {
  
    // copy every char *
    host->h_addr_list[i] = (char*)Malloc(strlen(sharehost->h_addr_list[i]));
    strcpy(host->h_addr_list[i], sharehost->h_addr_list[i]);
  }
  host->h_addr_list[i] = NULL;
  V(&mutex);
  return host;
}

int main(int argc, char* argv[]) {
  init_mutex();
  struct hostent host;
  gethostbyname_ts("127.0.0.1", &host);
  // result in &host
  return 0;
}

P27

I cannot explain.

发布了123 篇原创文章 · 获赞 76 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/swy_swy_swy/article/details/105306176
今日推荐