本文共 9273 字,大约阅读时间需要 30 分钟。
#include#include "csapp.h"void *thread(void *vargp);#define DEFAULT 4int 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;}
#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;}
#include#include "csapp.h"#define WRITE_LIMIT 100000#define PEOPLE 4static int readtimes;static int writetimes;static int readcnt;// if a reader is waiting when writing, reader first next roundstatic 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);}
#include#include "csapp.h"#define WRITE_LIMIT 100000#define PEOPLE 20 // 10 reader and 10 writer#define N 5static 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);}
#include#include "csapp.h"#define WRITE_LIMIT 100000#define PEOPLE 4static 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);}
#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\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;}
@@ -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
是
thread safe?
Yes, mutex make it safe reentrant? (我也不知道reentrant咋翻译) No, share the same mutex#include#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;}
I cannot explain.
转载地址:http://kfwai.baihongyu.com/