1. Study the following thread program. PLease pay attention to the global variables. (Can be download from week 5/6) /* cc thisfile.c -lthread */ #define _REENTRANT #include #include #define NUM_THREADS 6 static mutex_t Global_mutex; static int Global_data = 0; void *change_global_data(void *); /* for thr_create() */ void *schange_global_data(void *); /* for thr_create() */ main(int argc,char * argv[]) { int i=0; for (i=0; i< NUM_THREADS; i++) { thr_create(NULL, 0, change_global_data, NULL, 0, NULL); } for (i=0; i< NUM_THREADS; i++) { thr_create(NULL, 0, schange_global_data, NULL, 0, NULL); } while ((thr_join(NULL, NULL, NULL) == 0)); } void * change_global_data(void *null) { int i; mutex_lock(&Global_mutex); printf("%d is before \n", i); i=Global_data; printf("%d is after \n", i); Global_data++; sleep(1); printf("%d is global data\n",Global_data); mutex_unlock(&Global_mutex); return NULL; } void * schange_global_data(void *null) { int i; mutex_lock(&Global_mutex); printf("%d is before \n", i); i=Global_data; printf("%d is after \n", i); Global_data--; sleep(1); printf("%d is global data\n",Global_data); mutex_unlock(&Global_mutex); return NULL; } 2. Study the following sockrt programs using fork: (Can be download from week3/4) /**** Example of server using TCP protocol */ #include "inet.h" main(argc, argv) int argc; char *argv[]; { int sockfd, newsockfd, clilen, childpid; struct sockaddr_in cli_addr, serv_addr; pname = argv[0]; /*** Open a TCP socket (an Internet stream socket). ****/ if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) err_dump("server: can't open stream socket"); /** Bind our local address so that the client can send to us. **/ bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(SERV_TCP_PORT); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) <0) err_dump("server: can't bind local address"); listen(sockfd, 5); for (; ; ){ /* * Wait for a connection from a client process. * This is an example of a concurrent server. */ clilen = sizeof(cli_addr); newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) err_dump("server: accept error"); if( (childpid = fork())<0) err_dump("server: fork error"); else if (childpid == 0) { close(sockfd); str_echo(newsockfd); exit(0); } close(newsockfd); } } #define MAXLINE 512 str_echo(sockfd) int sockfd; { int n; char line[MAXLINE]; for ( ; ; ) { n = readline(sockfd, line, MAXLINE); if (n == 0) return; else if (n<0) err_dump("Str_echo: readline error"); if (written(sockfd, line, n) !=n) err_dump("str_echo: written error"); } } err_dump(a) char *a; { int i; for (i=0; i<=20; i++) { printf("%c", *a); a++; } } int readline(fd, ptr, maxlen) register int fd; register char *ptr; register int maxlen; { int n, rc; char c; for (n = 1; n < maxlen; n++) { if ( (rc = read(fd, &c, 1)) == 1) { *ptr ++=c; if (c == '\n') break; } else if (rc == 0) { if ( n == 1) return (0); else break; }else return (-1); } *ptr=0; return (n); } int written(fd, ptr, nbytes) register int fd; register char *ptr; register nbytes; { int nleft, nwritten; nleft = nbytes; while (nleft > 0) { nwritten = write(fd, ptr, nleft); if (nwritten <=0) return(nwritten); nleft -= nwritten; ptr += nwritten; } return(nbytes - nleft); } /*Example of client using TCP protocol */ #include "inet.h" main(argc, argv) int argc; char *argv[]; { int sockfd; struct sockaddr_in serv_addr; pname = argv[0]; /* Fill in the structure "seirv_addr" with the address of the server that we want to connect with. */ bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR); serv_addr.sin_port = htons(SERV_TCP_PORT); /* Open a TCP socket (an Internet stream socket). */ if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) err_sys("client: can't open stream socket"); /* Connect to the server. */ if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) err_sys("client: can't connect to server"); str_cli(stdin, sockfd); close(sockfd); exit(0); } #include #define MAXLINE 512 str_cli(fp, sockfd) register FILE *fp; register int sockfd; { int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; while (fgets(sendline, MAXLINE, fp) !=NULL) { n = strlen(sendline); if (written(sockfd, sendline, n) !=n) err_sys("str_cli: written error on socket"); /* Now read a line form the socket and write it to */ /* our standard output. */ n = readline(sockfd, recvline, MAXLINE); if (n < 0) err_sys("str_cli: readline error"); recvline[n] = 0; fputs(recvline, stdout); } } err_sys(a) char *a; { int i; for (i=0; i<=30; i++) { printf("%c", *a); a++; } } int readline(fd, ptr, maxlen) register int fd; register char *ptr; register int maxlen; { int n, rc; char c; for (n = 1; n < maxlen; n++) { if ( (rc = read(fd, &c, 1)) == 1) { *ptr ++=c; if (c == '\n') break; } else if (rc == 0) { if ( n == 1) return (0); else break; }else return (-1); } *ptr=0; return (n); } int written(fd, ptr, nbytes) register int fd; register char *ptr; register nbytes; { int nleft, nwritten; nleft = nbytes; while (nleft > 0) { nwritten = write(fd, ptr, nleft); if (nwritten <=0) return(nwritten); nleft -= nwritten; ptr += nwritten; } return(nbytes - nleft); } 3. Can you modify the client-server programs using thread?