本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
1.预先创建一个线程池,并让每个线程各自调用 accept
2.用互斥锁取代让每个线程都阻塞在 accept 调用之中的做法//用于维护关于每个线程基于信息的 Thread 结构
typedef struct {
pthread_t thread_tid; /* 线程 ID */
long thread_count; /* 处理的连接数 */
} Thread;
Thread *tptr; /* Thread 结构指针,指向一个用 calloc 产生的 Thread结构数组 */
//全局变量,包括监听套接字和一个需收所有线程共享的互斥锁变量
int listenfd, nthreads;
socklen_t addrlen;
pthread_mutex_t mlock;
/* include serv07 */
#include "unpthread.h"
#include "pthread07.h"
pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER;
int
main(int argc, char **argv)
{
int i;
void sig_int(int), thread_make(int);
//1.创建监听套接字
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: serv07 [ <host> ] <port#> <#threads>");
//2.增设一个命令行参数供用户指定预先派生的线程数
nthreads = atoi(argv[argc-1]);
tptr = Calloc(nthreads, sizeof(Thread));
//3.调用 thread_make 创建各个线程
for (i = 0; i < nthreads; i++)
thread_make(i); /* 只有父线程才返回 */
//4.设置中断信号 SIGINT 的处理函数
Signal(SIGINT, sig_int);
//5.所有事情都由子线程做,主线程阻塞在 pause()
for ( ; ; )
pause(); /* everything done by threads */
}
/* end serv07 */
//中断信号 SIGINT 处理函数
void
sig_int(int signo)
{
int i;
void pr_cpu_time(void);
//调用 pr_cpu_time 统计资源利用统计
//在预先派生子进程的代码中还要先给每个子进程发送 SIGTERM 信号终止它们再统计。
//这里由于是线程,而子线程与主线程是在同一个地址空间的,当主线程终止时,子线程也会终止。
pr_cpu_time();
for (i = 0; i < nthreads; i++)
printf("thread %d, %ld connections\n", i, tptr[i].thread_count);
exit(0);
}
void
thread_make(int i)
{
void *thread_main(void *);
//创建线程并使之执行 thread_main 函数,该函数的唯一参数是本线程在 Thread 结构数组中的下标
Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void *) i);
return; /* main thread returns */
}
void *
thread_main(void *arg)
{
int connfd;
void web_child(int);
socklen_t clilen;
struct sockaddr *cliaddr;
cliaddr = Malloc(addrlen);
printf("thread %d starting\n", (int) arg);
for ( ; ; ) {
clilen = addrlen;
//在调用 accept 前后调用 pthread_mutex_lock 和 pthread_mutex_unlock 加以保护
Pthread_mutex_lock(&mlock);
connfd = Accept(listenfd, cliaddr, &clilen);
Pthread_mutex_unlock(&mlock);
tptr[(int) arg].thread_count++;
web_child(connfd); /* process request */
Close(connfd);
}
}