/*****************************************************************************/ /* TCP预先派生子进程服务器程序 */ /*****************************************************************************/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #include <errno.h> #include <pthread.h> #include <sys/mman.h> #include <sys/resource.h>
#define MAXLINE 256 #define MAXN 16384
static int nchildren; static pid_t *pids; static pthread_mutex_t *mptr;
void sig_int( int signo ); int tcp_listen( int nPort, int nMax ); pid_t child_make( int i, int listenfd ); void child_main( int i, int listenfd ); void web_child( int sockfd ); ssize_t readn( int fd, void *vptr, size_t n ); ssize_t writen( int fd, void *vptr, size_t n ); ssize_t readline( int fd, void *vptr, size_t maxlen ); void pr_cpu_time( void );
/*****************************************************************************/ /* */ /*****************************************************************************/ int main( int argc, char *argv[] ) { int listenfd, i; int nPort, nMax = 5; if (argc != 3) { printf( "usage: %s <#port> <#children>\n", argv[0] ); exit( 1 ); }
nPort = atoi( argv[1] );
listenfd = tcp_listen( nPort, nMax ); if (listenfd < 0) { printf( "starting service failed!\n" ); exit( 1 ); } nchildren = atoi( argv[argc-1] ); pids = calloc( nchildren, sizeof(pid_t) ); for (i=0; i<nchildren; i++) { pids[i] = child_make( i, listenfd ); /* parent returns */ } signal( SIGINT, sig_int ); for (;;) { pause(); /* everything done by children */ } }
/*****************************************************************************/ /* */ /*****************************************************************************/ pid_t child_make( int i, int listenfd ) { pid_t pid; if ((pid = fork()) > 0) { return( pid ); /* parent */ } child_main( i, listenfd ); /*never returns */ return 0; }
/*****************************************************************************/ /* */ /*****************************************************************************/ void child_main( int i, int listenfd ) { int connfd;
printf( "child %ld starting\n", (long)getpid() );
for (;;) { connfd = accept( listenfd, NULL, NULL ); web_child( connfd ); /* process the request */ close( connfd ); } }
/*****************************************************************************/ /* */ /*****************************************************************************/ void web_child( int sockfd ) { int ntowrite; ssize_t nread; char line[MAXLINE], result[MAXN]; for(;;) { if ((nread = read( sockfd, line, MAXLINE)) == 0) { return; }
ntowrite = atoi( line ); if ((ntowrite <= 0) || (ntowrite > MAXN)) { printf( "client request for %d bytes", ntowrite ); return; } writen( sockfd, result, ntowrite ); } }
/*****************************************************************************/ /* */ /*****************************************************************************/ int tcp_listen( int nPort, int nMax ) { int sockfd; struct sockaddr_in addrin; struct sockaddr *paddr = (struct sockaddr *)&addrin; if ((nPort <= 0) || (nMax <= 0)) { return -1; } memset( &addrin, 0x00, sizeof(addrin) ); addrin.sin_family = AF_INET; addrin.sin_addr.s_addr = htonl( INADDR_ANY ); addrin.sin_port = htons( nPort ); sockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) { return -2; } if (bind(sockfd, paddr, sizeof(addrin)) != 0) { close( sockfd ); return -3; } if (listen(sockfd, nMax) != 0) { close( sockfd ); return -4; } return sockfd; }
/*****************************************************************************/ /* */ /*****************************************************************************/ ssize_t readn( int fd, void *vptr, size_t n ) { ssize_t nleft; ssize_t nread; char *ptr;
ptr = vptr; nleft = n; while(nleft > 0) { if ((nread = read(fd, ptr, nleft)) < 0) { if (errno == EINTR) { nread = 0; /* and call read() again */ } else { return(-1); } } else if (nread == 0) { break; /* EOF */ } nleft -= nread; ptr += nread; } return(n - nleft); /* return >= 0 */ }
/*****************************************************************************/ /* */ /*****************************************************************************/ ssize_t writen( int fd, void *vptr, size_t n ) { ssize_t nleft; ssize_t nwritten; const char *ptr;
ptr = vptr; nleft = n; while(nleft > 0) { if ((nwritten = write(fd, ptr, nleft)) <= 0) { if (errno == EINTR) { nwritten = 0; /* and call write() again */ } else { return(-1); /* error */ } } nleft -= nwritten; ptr += nwritten; } return(n); }
/*****************************************************************************/ /* */ /*****************************************************************************/ ssize_t readline( int fd, void *vptr, size_t maxlen ) { ssize_t n, rc; char c, *ptr; ptr = vptr; for (n=1; n<maxlen; n++) { again: if ((rc = read(fd, &c, 1)) == 1) { *ptr++ = c; if (c == '\n') { break; /* newline is stored, like fgets() */ } else if (rc == 0) { if (n == 1) { return( 0 ); /* EOF, no data read */ } else { break; /* EOF, some data was read */ } } else { if (errno == EINTR) { goto again; } return( -1 ); /* error, errno set by read() */ } } } *ptr = 0; /* null terminate like fgets() */ return( n ); }
/*****************************************************************************/ /* */ /*****************************************************************************/ void my_lock_init( void ) { int fd; pthread_mutexattr_t mattr; fd = open( "/dev/zero", O_RDWR, 0 ); mptr = mmap( 0, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ); close( fd ); pthread_mutexattr_init( &mattr ); pthread_mutexattr_setpshared( &mattr, PTHREAD_PROCESS_SHARED ); pthread_mutex_init( mptr, &mattr ); }
/*****************************************************************************/ /* */ /*****************************************************************************/ void my_lock_wait( void ) { pthread_mutex_lock( mptr ); }
/*****************************************************************************/ /* */ /*****************************************************************************/ void my_lock_release( void ) { pthread_mutex_unlock( mptr ); }
/*****************************************************************************/ /* */ /*****************************************************************************/ void sig_int( int signo ) { int i; /* terminate all children */ for (i=0; i<nchildren; i++) { kill( pids[i], SIGTERM ); } while(wait(NULL)>0) ; if (errno != ECHILD) { printf( "wait error" ); } pr_cpu_time(); exit(0); }
void pr_cpu_time( void ) { double user, sys; struct rusage myusage, childusage; if (getrusage(RUSAGE_SELF, &myusage) < 0) { printf( "getrusage error\n" ); } if (getrusage(RUSAGE_CHILDREN, &childusage) < 0) { printf( "getrusage error\n" ); } user = (double)myusage.ru_utime.tv_sec + myusage.ru_utime.tv_usec/1000000.0; user += (double)childusage.ru_utime.tv_sec + childusage.ru_utime.tv_usec/1000000.0; sys = (double)myusage.ru_stime.tv_sec + myusage.ru_stime.tv_usec/1000000.0; sys += (double)childusage.ru_stime.tv_sec + childusage.ru_stime.tv_usec/1000000.0; printf( "\nuser time=%g, sys time=%g\n", user, sys ); }
|