上篇
《客户/服务器程序设计范式--并发服务器程序,accept使用文件上锁保护》使用文件锁保护accept涉及文件系统操作,可能比较耗时。这篇,我们使用线程锁保护accept,因为这种方法不仅适用于同一个进程内各线程之间上锁,而且适用于不同进程之间的上锁。但是在不同进程之间使用线程锁要求:1.互斥锁变量必须存放在由所有进程共享的内存中,这里我们使用共享内存的方式。2.必须告知线程库函数这是在不同进程之间共享的互斥锁。这里我们使用Pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);来通知线程库函数。
serv04.c
--------------------------------
#include "global.h"
static int nchildren; static pid_t *pids;
int main(int argc, char **argv) { int listenfd, i; socklen_t addrlen; void sig_int(int); pid_t child_make(int, int, int);
if (argc == 3) listenfd = Tcp_listen(NULL, argv[1], &addrlen); else if (argc == 4) listenfd = Tcp_listen(argv[1], argv[2], &addrlen); else err_quit("usage: serv04 [ ] <#children>"); nchildren = atoi(argv[argc-1]); pids = Calloc(nchildren, sizeof(pid_t));
my_lock_init(NULL); for (i = 0; i < nchildren; i++) pids[i] = child_make(i, listenfd, addrlen); /* parent returns */
Signal(SIGINT, sig_int);
for ( ; ; ) pause(); /* everything done by children */ }
void sig_int(int signo) { int i; void pr_cpu_time(void);
/* terminate all children */ for (i = 0; i < nchildren; i++) kill(pids[i], SIGTERM); while (wait(NULL) > 0) /* wait for all children */ ; if (errno != ECHILD) err_sys("wait error");
pr_cpu_time(); exit(0); }
|
child04.c
-------------------------------
#include "global.h"
pid_t child_make(int i, int listenfd, int addrlen) { pid_t pid; void child_main(int, int, int);
if ( (pid = Fork()) > 0) return(pid); /* parent */
child_main(i, listenfd, addrlen); /* never returns */ }
void child_main(int i, int listenfd, int addrlen) { int connfd; void web_child(int); socklen_t clilen; struct sockaddr *cliaddr;
cliaddr = Malloc(addrlen);
printf("child %ld starting\n", (long) getpid()); for ( ; ; ) { clilen = addrlen; my_lock_wait(); connfd = Accept(listenfd, cliaddr, &clilen); my_lock_release();
web_child(connfd); /* process the request */ Close(connfd); } }
|
lock_pthread.c
------------------------------------
/* include my_lock_init */ #include "unpthread.h" #include <sys/mman.h>
static pthread_mutex_t *mptr; /* actual mutex will be in shared memory */
void my_lock_init(char *pathname) { 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); } /* end my_lock_init */
/* include my_lock_wait */ void my_lock_wait() { Pthread_mutex_lock(mptr); }
void my_lock_release() { Pthread_mutex_unlock(mptr); } /* end my_lock_wait */
|
执行结果:
$ ./serv04 173.26.100.162 12345 10
child 16083 starting
child 16084 starting
child 16085 starting
child 16086 starting
child 16087 starting
child 16088 starting
child 16089 starting
child 16090 starting
child 16091 starting
child 16092 starting
user time = 0.012, sys time = 0.124007
程序源代码包见<<客户/服务器程序设计范式---迭代服务器程序>>后的附件
阅读(640) | 评论(0) | 转发(0) |