线程池思路
1、makefile
SRCS:=$(wildcard *.c) OBJS:=$(SRCS:%.c=%.o) CC:=gcc server:$(OBJS) $(CC) $^ -o $@ -lpthread %.o:%.c $(CC) -c $^ -o $@ -g .PHONY:clean rebuild clean: $(RM) $(OBJS) server rebuild:clean server
2、终端输入设计
./server ip port 工作线程数量
3、建立线程池
threadPool_t threadPool;
threadPoolInit(&threadPool,workerNum);
4、建立工作线程
int workerNum = atoi(argv[3]);
makeWorker(&threadPool);
5、tcp连接
tcpInit(argv[1],argv[2],&sockFd);
6、建立epoll监听,子进程监听网络socket与父进程管道exitPipe[0]读端
int epfd = epoll_create(10);
epollAdd(sockFd,epfd);
epollAdd(exitPipe[0],epfd);
struct epoll_event readyList[2];
7、工作线程实现,从事件队列中取任务(共享资源区域需上锁,且从队列任务中取出后任务队列自然要把它dequeue)
while(1){ int netFd; pthread_mutex_lock(&pThreadPool->mutex); pthread_cleanup_push(unlock,&pThreadPool->mutex); while(pThreadPool->taskQueue.size == 0 && pThreadPool->isThreadPoolRunning == 1){ pthread_cond_wait(&pThreadPool->cond,&pThreadPool->mutex); } if(pThreadPool->isThreadPoolRunning == 0){ puts("child quit"); pthread_exit(NULL);//不能用return,与cleanup冲突 } puts("GetTask"); netFd = pThreadPool->taskQueue.pFront->netFd; deQueue(&pThreadPool->taskQueue); pthread_cleanup_pop(1); handleEvent(netFd); printf("thread done!, tid = %lu\n", pthread_self());
8、主进程与子进程直接管道通信,主进程专门负责接收信号
int exitPipe[2];
pipe(exitPipe);
9、上锁,条件信号,资源清理函数(cleanup避免子线程带锁而死),全局变量isThreadPoolRunning,以此实现优雅的退出。

w
浙公网安备 33010602011771号