澳门金莎娱乐手机版 操作系统 线程池的相关信息,服务器代码

线程池的相关信息,服务器代码

instr(:ins(:task(pickupX)(:cond(sortXremotecontrol)))(:task(pickupX)(:cond(colorXblack)(sortXremotecontrol)))(:task(putonXY)(:cond(sortXcan)(sortYworktable)))(:task(putonXY)(:cond(sortXcup)(sortYworktable)))(:task(gotoX)(:cond(sortXchair)))(:cons_notnot(:info(onXY卡塔尔(قطر‎(:cond(sortXremotecontrol卡塔尔(colorXyellow卡塔尔(قطر‎(sortYteapoy卡塔尔(英语:State of Qatar)卡塔尔(英语:State of Qatar)卡塔尔卡塔尔(قطر‎卡塔尔(قطر‎/instrnlPickuparemotecontrol.Pickuptheremotecontrolwhichisblack.Puta佳能theworktable.Putacupontheworktable.Gotochair.Thegreencanmustbeontheplate.Theremotecontrolwhichisyellowmustbeontheteapoy./nl/testC语言张开那样一个test2.xml文书,怎么样将<nl>到</nl>中的内容以单词为成分,按一句话风流倜傥行存入数组,并安装能够搜索关键词大器晚成类词语的指针。

率先部分为头文件

 1 #ifndef __THREADPOOL_H_
 2 #define __THREADPOOL_H_
 3 
 4 typedef struct threadpool_t threadpool_t;
 5 
 6 /**
 7  * @function threadpool_create
 8  * @descCreates a threadpool_t object.
 9  * @param thr_num  thread num
10  * @param max_thr_num  max thread size
11  * @param queue_max_size   size of the queue.
12  * @return a newly created thread pool or NULL
13  */
14 threadpool_t *threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size);
15 
16 /**
17  * @function threadpool_add
18  * @desc add a new task in the queue of a thread pool
19  * @param pool     Thread pool to which add the task.
20  * @param function Pointer to the function that will perform the task.
21  * @param argument Argument to be passed to the function.
22  * @return 0 if all goes well,else -1
23  */
24 int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg);
25 
26 /**
27  * @function threadpool_destroy
28  * @desc Stops and destroys a thread pool.
29  * @param pool  Thread pool to destroy.
30  * @return 0 if destory success else -1
31  */
32 int threadpool_destroy(threadpool_t *pool);
33 
34 /**
35  * @desc get the thread num
36  * @pool pool threadpool
37  * @return # of the thread
38  */
39 int threadpool_all_threadnum(threadpool_t *pool);
40 
41 /**
42  * desc get the busy thread num
43  * @param pool threadpool
44  * return # of the busy thread
45  */
46 int threadpool_busy_threadnum(threadpool_t *pool);
47 
48 #endif

服务器函数施行流程

main

init_system

creat_pthread_pool

child_work

thread_manager

task_manager

process_client

monitor

sys_clean

第二部分为自完结线程池代码(对libevent库进行一些精简,显示逻辑)

Makefile文件

[plain] view
plain copy

 print?图片 1图片 2

  1. CC = gcc  
  2. TARGET = pthread_pool  
  3. SRC = pthread_pool.c base.c  
  4. OBJECT = pthread_pool.o  base.o  
  5. INCLUDES = -I./  
  6. LDFLAGS = -lpthread  
  7.   
  8. all:$(TARGET)  
  9.   
  10. $(OBJECT):$(SRC)  
  11.     $(CC) -c $(INCLUDES) ${SRC}  
  12.   
  13. $(TARGET):$(OBJECT)  
  14.     $(CC) -o $@ $(OBJECT) $(LDFLAGS)  
  15.   
  16. .PHONY:clean  
  17.   
  18. clean:  
  19.     @rm -rf $(OBJECT) $(TARGET) *~  
  1 #include <stdlib.h>
  2 #include <pthread.h>
  3 #include <unistd.h>
  4 #include <assert.h>
  5 #include <stdio.h>
  6 #include <string.h>
  7 #include <signal.h>
  8 #include <errno.h>
  9 #include "threadpool.h"
 10 
 11 #define DEFAULT_TIME 10                 /*10s检测一次*/
 12 #define MIN_WAIT_TASK_NUM 10            /*如果queue_size > MIN_WAIT_TASK_NUM 添加新的线程到线程池*/ 
 13 #define DEFAULT_THREAD_VARY 10          /*每次创建和销毁线程的个数*/
 14 #define true 1
 15 #define false 0
 16 
 17 typedef struct {
 18     void *(*function)(void *);          /* 函数指针,回调函数 */
 19     void *arg;                          /* 上面函数的参数 */
 20 } threadpool_task_t;                    /* 各子线程任务结构体 */
 21 
 22 /* 描述线程池相关信息 */
 23 struct threadpool_t {
 24     pthread_mutex_t lock;               /* 用于锁住本结构体 */    
 25     pthread_mutex_t thread_counter;     /* 记录忙状态线程个数de琐 -- busy_thr_num */
 26 
 27     pthread_cond_t queue_not_full;      /* 当任务队列满时,添加任务的线程阻塞,等待此条件变量 */
 28     pthread_cond_t queue_not_empty;     /* 任务队列里不为空时,通知等待任务的线程 */
 29 
 30     pthread_t *threads;                 /* 存放线程池中每个线程的tid。数组 */
 31     pthread_t adjust_tid;               /* 存管理线程tid */
 32     threadpool_task_t *task_queue;      /* 任务队列(数组首地址) */
 33 
 34     int min_thr_num;                    /* 线程池最小线程数 */
 35     int max_thr_num;                    /* 线程池最大线程数 */
 36     int live_thr_num;                   /* 当前存活线程个数 */
 37     int busy_thr_num;                   /* 忙状态线程个数 */
 38     int wait_exit_thr_num;              /* 要销毁的线程个数 */
 39 
 40     int queue_front;                    /* task_queue队头下标 */
 41     int queue_rear;                     /* task_queue队尾下标 */
 42     int queue_size;                     /* task_queue队中实际任务数 */
 43     int queue_max_size;                 /* task_queue队列可容纳任务数上限 */
 44 
 45     int shutdown;                       /* 标志位,线程池使用状态,true或false */
 46 };
 47 
 48 void *threadpool_thread(void *threadpool);
 49 
 50 void *adjust_thread(void *threadpool);
 51 
 52 int is_thread_alive(pthread_t tid);
 53 int threadpool_free(threadpool_t *pool);
 54 
 55 //threadpool_create(3,100,100);  
 56 threadpool_t *threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size)
 57 {
 58     int i;
 59     threadpool_t *pool = NULL;
 60     do {
 61         if((pool = (threadpool_t *)malloc(sizeof(threadpool_t))) == NULL) {  
 62             printf("malloc threadpool fail");
 63             break;                                      /*跳出do while*/
 64         }
 65 
 66         pool->min_thr_num = min_thr_num;
 67         pool->max_thr_num = max_thr_num;
 68         pool->busy_thr_num = 0;
 69         pool->live_thr_num = min_thr_num;               /* 活着的线程数 初值=最小线程数 */
 70         pool->wait_exit_thr_num = 0;
 71         pool->queue_size = 0;                           /* 有0个产品 */
 72         pool->queue_max_size = queue_max_size;
 73         pool->queue_front = 0;
 74         pool->queue_rear = 0;
 75         pool->shutdown = false;                         /* 不关闭线程池 */
 76 
 77         /* 根据最大线程上限数, 给工作线程数组开辟空间, 并清零 */
 78         pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num); 
 79         if (pool->threads == NULL) {
 80             printf("malloc threads fail");
 81             break;
 82         }
 83         memset(pool->threads, 0, sizeof(pthread_t)*max_thr_num);
 84 
 85         /* 队列开辟空间 */
 86         pool->task_queue = (threadpool_task_t *)malloc(sizeof(threadpool_task_t)*queue_max_size);
 87         if (pool->task_queue == NULL) {
 88             printf("malloc task_queue fail");
 89             break;
 90         }
 91 
 92         /* 初始化互斥琐、条件变量 */
 93         if (pthread_mutex_init(&(pool->lock), NULL) != 0
 94                 || pthread_mutex_init(&(pool->thread_counter), NULL) != 0
 95                 || pthread_cond_init(&(pool->queue_not_empty), NULL) != 0
 96                 || pthread_cond_init(&(pool->queue_not_full), NULL) != 0)
 97         {
 98             printf("init the lock or cond fail");
 99             break;
100         }
101 
102         /* 启动 min_thr_num 个 work thread */
103         for (i = 0; i < min_thr_num; i++) {
104             pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);/*pool指向当前线程池*/
105             printf("start thread 0x%x...n", (unsigned int)pool->threads[i]);
106         }
107         pthread_create(&(pool->adjust_tid), NULL, adjust_thread, (void *)pool);/* 启动管理者线程 */
108 
109         return pool;
110 
111     } while (0);
112 
113     threadpool_free(pool);      /* 前面代码调用失败时,释放poll存储空间 */
114 
115     return NULL;
116 }
117 
118 /* 向线程池中 添加一个任务 */
119 //threadpool_add(thp, process, (void*)&num[i]);   /* 向线程池中添加任务 process: 小写---->大写*/
120 
121 int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg)
122 {
123     pthread_mutex_lock(&(pool->lock));
124 
125     /* ==为真,队列已经满, 调wait阻塞 */
126     while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)) {
127         pthread_cond_wait(&(pool->queue_not_full), &(pool->lock));
128     }
129     if (pool->shutdown) {
130         pthread_cond_broadcast(&(pool->queue_not_empty));
131         pthread_mutex_unlock(&(pool->lock));
132         return 0;
133     }
134 
135     /* 清空 工作线程 调用的回调函数 的参数arg */
136     if (pool->task_queue[pool->queue_rear].arg != NULL) {
137         pool->task_queue[pool->queue_rear].arg = NULL;
138     }
139     /*添加任务到任务队列里*/
140     pool->task_queue[pool->queue_rear].function = function;
141     pool->task_queue[pool->queue_rear].arg = arg;
142     pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;       /* 队尾指针移动, 模拟环形 */
143     pool->queue_size++;
144 
145     /*添加完任务后,队列不为空,唤醒线程池中 等待处理任务的线程*/
146     pthread_cond_signal(&(pool->queue_not_empty));
147     pthread_mutex_unlock(&(pool->lock));
148 
149     return 0;
150 }
151 
152 /* 线程池中各个工作线程 */
153 void *threadpool_thread(void *threadpool)
154 {
155     threadpool_t *pool = (threadpool_t *)threadpool;
156     threadpool_task_t task;
157 
158     while (true) {
159         /* Lock must be taken to wait on conditional variable */
160         /*刚创建出线程,等待任务队列里有任务,否则阻塞等待任务队列里有任务后再唤醒接收任务*/
161         pthread_mutex_lock(&(pool->lock));
162 
163         /*queue_size == 0 说明没有任务,调 wait 阻塞在条件变量上, 若有任务,跳过该while*/
164         while ((pool->queue_size == 0) && (!pool->shutdown)) {  
165             printf("thread 0x%x is waitingn", (unsigned int)pthread_self());
166             pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));
167 
168             /*清除指定数目的空闲线程,如果要结束的线程个数大于0,结束线程*/
169             if (pool->wait_exit_thr_num > 0) {
170                 pool->wait_exit_thr_num--;
171 
172                 /*如果线程池里线程个数大于最小值时可以结束当前线程*/
173                 if (pool->live_thr_num > pool->min_thr_num) {
174                     printf("thread 0x%x is exitingn", (unsigned int)pthread_self());
175                     pool->live_thr_num--;
176                     pthread_mutex_unlock(&(pool->lock));
177 
178                     pthread_exit(NULL);
179                 }
180             }
181         }
182 
183         /*如果指定了true,要关闭线程池里的每个线程,自行退出处理---销毁线程池*/
184         if (pool->shutdown) {
185             pthread_mutex_unlock(&(pool->lock));
186             printf("thread 0x%x is exitingn", (unsigned int)pthread_self());
187             pthread_detach(pthread_self());
188             pthread_exit(NULL);     /* 线程自行结束 */
189         }
190 
191         /*从任务队列里获取任务, 是一个出队操作*/
192         task.function = pool->task_queue[pool->queue_front].function;
193         task.arg = pool->task_queue[pool->queue_front].arg;
194 
195         pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size;       /* 出队,模拟环形队列 */
196         pool->queue_size--;
197 
198         /*通知可以有新的任务添加进来*/
199         pthread_cond_broadcast(&(pool->queue_not_full));
200 
201         /*任务取出后,立即将 线程池琐 释放*/
202         pthread_mutex_unlock(&(pool->lock));
203 
204         /*执行任务*/ 
205         printf("thread 0x%x start workingn", (unsigned int)pthread_self());
206         pthread_mutex_lock(&(pool->thread_counter));                            /*忙状态线程数变量琐*/
207         pool->busy_thr_num++;                                                   /*忙状态线程数+1*/
208         pthread_mutex_unlock(&(pool->thread_counter));
209 
210         (*(task.function))(task.arg);                                           /*执行回调函数任务*/
211         //task.function(task.arg);                                              /*执行回调函数任务*/
212 
213         /*任务结束处理*/ 
214         printf("thread 0x%x end workingn", (unsigned int)pthread_self());
215         pthread_mutex_lock(&(pool->thread_counter));
216         pool->busy_thr_num--;                                       /*处理掉一个任务,忙状态数线程数-1*/
217         pthread_mutex_unlock(&(pool->thread_counter));
218     }
219 
220     pthread_exit(NULL);
221 }
222 
223 /* 管理线程 */
224 void *adjust_thread(void *threadpool)
225 {
226     int i;
227     threadpool_t *pool = (threadpool_t *)threadpool;
228     while (!pool->shutdown) {
229 
230         sleep(DEFAULT_TIME);                                    /*定时 对线程池管理*/
231 
232         pthread_mutex_lock(&(pool->lock));
233         int queue_size = pool->queue_size;                      /* 关注 任务数 */
234         int live_thr_num = pool->live_thr_num;                  /* 存活 线程数 */
235         pthread_mutex_unlock(&(pool->lock));
236 
237         pthread_mutex_lock(&(pool->thread_counter));
238         int busy_thr_num = pool->busy_thr_num;                  /* 忙着的线程数 */
239         pthread_mutex_unlock(&(pool->thread_counter));
240 
241         /* 创建新线程 算法: 任务数大于最小线程池个数, 且存活的线程数少于最大线程个数时 如:30>=10 && 40<100*/
242         if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num) {
243             pthread_mutex_lock(&(pool->lock));  
244             int add = 0;
245 
246             /*一次增加 DEFAULT_THREAD 个线程*/
247             for (i = 0; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY
248                     && pool->live_thr_num < pool->max_thr_num; i++) {
249                 if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i])) {
250                     pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);
251                     add++;
252                     pool->live_thr_num++;
253                 }
254             }
255 
256             pthread_mutex_unlock(&(pool->lock));
257         }
258 
259         /* 销毁多余的空闲线程 算法:忙线程X2 小于 存活的线程数 且 存活的线程数 大于 最小线程数时*/
260         if ((busy_thr_num * 2) < live_thr_num  &&  live_thr_num > pool->min_thr_num) {
261 
262             /* 一次销毁DEFAULT_THREAD个线程, 隨機10個即可 */
263             pthread_mutex_lock(&(pool->lock));
264             pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;      /* 要销毁的线程数 设置为10 */
265             pthread_mutex_unlock(&(pool->lock));
266 
267             for (i = 0; i < DEFAULT_THREAD_VARY; i++) {
268                 /* 通知处在空闲状态的线程, 他们会自行终止*/
269                 pthread_cond_signal(&(pool->queue_not_empty));
270             }
271         }
272     }
273 
274     return NULL;
275 }
276 
277 int threadpool_destroy(threadpool_t *pool)
278 {
279     int i;
280     if (pool == NULL) {
281         return -1;
282     }
283     pool->shutdown = true;
284 
285     /*先销毁管理线程*/
286     pthread_join(pool->adjust_tid, NULL);
287 
288     for (i = 0; i < pool->live_thr_num; i++) {
289         /*通知所有的空闲线程*/
290         pthread_cond_broadcast(&(pool->queue_not_empty));
291     }
292     for (i = 0; i < pool->live_thr_num; i++) {
293         pthread_join(pool->threads[i], NULL);
294     }
295     threadpool_free(pool);
296 
297     return 0;
298 }
299 
300 int threadpool_free(threadpool_t *pool)
301 {
302     if (pool == NULL) {
303         return -1;
304     }
305 
306     if (pool->task_queue) {
307         free(pool->task_queue);
308     }
309     if (pool->threads) {
310         free(pool->threads);
311         pthread_mutex_lock(&(pool->lock));
312         pthread_mutex_destroy(&(pool->lock));
313         pthread_mutex_lock(&(pool->thread_counter));
314         pthread_mutex_destroy(&(pool->thread_counter));
315         pthread_cond_destroy(&(pool->queue_not_empty));
316         pthread_cond_destroy(&(pool->queue_not_full));
317     }
318     free(pool);
319     pool = NULL;
320 
321     return 0;
322 }
323 
324 int threadpool_all_threadnum(threadpool_t *pool)
325 {
326     int all_threadnum = -1;
327     pthread_mutex_lock(&(pool->lock));
328     all_threadnum = pool->live_thr_num;
329     pthread_mutex_unlock(&(pool->lock));
330     return all_threadnum;
331 }
332 
333 int threadpool_busy_threadnum(threadpool_t *pool)
334 {
335     int busy_threadnum = -1;
336     pthread_mutex_lock(&(pool->thread_counter));
337     busy_threadnum = pool->busy_thr_num;
338     pthread_mutex_unlock(&(pool->thread_counter));
339     return busy_threadnum;
340 }
341 
342 int is_thread_alive(pthread_t tid)
343 {
344     int kill_rc = pthread_kill(tid, 0);     //发0号信号,测试线程是否存活
345     if (kill_rc == ESRCH) {
346         return false;
347     }
348 
349     return true;
350 }
351 
352 /*测试*/ 
353 
354 #if 1
355 /* 线程池中的线程,模拟处理业务 */
356 void *process(void *arg)
357 {
358     printf("thread 0x%x working on task %dn ",(unsigned int)pthread_self(),(int)arg);
359     sleep(1);  //小---大写
360     printf("task %d is endn",(int)arg);
361 
362     return NULL;
363 }
364 
365 int main(void)
366 {
367     /*threadpool_t *threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size);*/
368 
369     threadpool_t *thp = threadpool_create(3,100,100);   /*创建线程池,池里最小3个线程,最大100,队列最大100*/
370     printf("pool inited");
371 
372     //int *num = (int *)malloc(sizeof(int)*20);
373     int num[20], i;
374     for (i = 0; i < 20; i++) {
375         num[i]=i;
376         printf("add task %dn",i);
377         threadpool_add(thp, process, (void*)&num[i]);   /* 向线程池中添加任务 */
378     }
379     sleep(10);                                          /* 等子线程完成任务 */
380     threadpool_destroy(thp);
381 
382     return 0;
383 }
384 
385 #endif

服务器代码

=======================

头文件

[cpp] view
plain copy

 print?图片 3图片 4

  1. #ifndef __PTHREAD_POOL_H__  
  2.   
  3. #define __PTHREAD_POOL_H__  
  4.   
  5. #include <stdio.h>  
  6. #include <pthread.h>  
  7. #include <stdlib.h>  
  8. #include <string.h>  
  9. #include <time.h>  
  10. #include <sys/syscall.h>  
  11. #include <sys/types.h>  
  12. #include <unistd.h>  
  13. #include <assert.h>  
  14. #include <sys/stat.h>  
  15. #include <sys/types.h>  
  16. #include <fcntl.h>  
  17. #include <sys/socket.h>  
  18. #include <netinet/in.h>  
  19. #include <arpa/inet.h>  
  20. #include <net/if.h>  
  21. #include <sys/ioctl.h>  
  22. #include <errno.h>  
  23.   
  24. #define THREAD_MAX_NUM  100     /* max number of thread. */  
  25. #define THREAD_DEF_NUM  20      /* by default ,number of thread. */  
  26. #define THREAD_MIN_NUM  5       /* min number of thread pool. */  
  27. #define LISNUM<span style=”white-space:pre”>  </span>5  
  28. #define PORT    9001  
  29. #define MAXBUF  1024  
  30.   
  31.   
  32. /* 
  33.  * *ds of the every task. make all task in a single link 
  34.  */  
  35. //任务布局节点,用于描述每一种职责的切实性质  
  36. typedef struct task_node  
  37. {  
  38.     void *arg;                              /* fun arg. */  
  39.     void *(*fun)(void *);                   /* the real work of the task. */  
  40.     pthread_t       tid;            /* which thread exec this task. */  
  41.     int         work_id;        /* task id. */  
  42.     int         flag;           /* 1: assigned, 0: unassigned. */  
  43.     struct task_node    *next;  
  44.     pthread_mutex_t     mutex;          /* when modify this ds and exec the work,lock the task ds. */  
  45. } TASK_NODE;  
  46.   
  47.   
  48. /* 
  49.  * *the ds  of the task_queue 
  50.  */  
  51. //职务队列构造,用于调控总体职责队列  
  52. typedef struct task_queue  
  53. {  
  54.     pthread_mutex_t     mutex;  
  55.     pthread_cond_t      cond;   /* when no task, the manager thread wait for ;when a new task come, signal. */  
  56.     struct task_node    *head;  /* point to the task_link. */  
  57.     int         number; /* current number of task, include unassinged and assigned but no finished. */  
  58. } TASK_QUEUE_T;  
  59.   
  60.   
  61. /* 
  62.  * *the ds of every thread, make all thread in a double link queue. 
  63.  */  
  64. //线程构造节点,用于描述每一个线程的切实可行性质  
  65. typedef struct pthread_node  
  66. {  
  67.     pthread_t       tid;    /* the pid of this thread in kernel,the value is  syscall return . */  
  68.     int         flag;   /*  1:busy, 0:free. */  
  69.     struct task_node    *work;  /*  if exec a work, which work. */  
  70.     struct pthread_node *next;  
  71.     struct pthread_node *prev;  
  72.     pthread_cond_t      cond;   /* when assigned a task, signal this child thread by manager. */  
  73.     pthread_mutex_t     mutex;  
  74. } THREAD_NODE;  
  75.   
  76.   
  77. /* 
  78.  * *the ds of the thread queue 
  79.  */  
  80. //线程队列布局,用于调节空闲线程队列和劳顿线程队列  
  81. typedef struct pthread_queue  
  82. {  
  83.     int         number; /* the number of thread in this queue. */  
  84.     struct pthread_node *head;  
  85.     struct pthread_node *rear;  
  86.     pthread_cond_t      cond;   /* when no idle thread, the manager wait for ,or when a thread return with idle, signal. */  
  87.     pthread_mutex_t     mutex;  
  88. } PTHREAD_QUEUE_T;  
  89.   
  90. //在pthread_poll(卡塔尔中定义的多少个布局的指针  
  91. extern PTHREAD_QUEUE_T  *pthread_queue_idle;    /* the idle thread double link queue. */  
  92. extern PTHREAD_QUEUE_T  *pthread_queue_busy;    /* the work thread double link queue. */  
  93. extern TASK_QUEUE_T *task_queue_head;       /* the task queuee single link list. */  
  94.   
  95. void *child_work( void *ptr );  
  96.   
  97. void create_pthread_pool( void );  
  98.   
  99. void init_system( void );  
  100.   
  101. void *thread_manager( void *ptr );  
  102.   
  103. void *prcoess_client( void *ptr );  
  104.   
  105. void *task_manager( void *ptr );  
  106.   
  107. void *monitor( void *ptr );  
  108.   
  109. void sys_clean( void );  
  110.   
  111. #endif  

线程池的有关音信:

功底函数

[cpp] view
plain copy

 print?图片 5图片 6

  1. #include “pthread_pool.h”  
  2.   
  3.   
  4. /* 
  5.  * *child_work:the code exec in child thread 
  6.  * *ptr: the ds of thread_node of current thread. 
  7.  * *return :nothing.void * just avoid warning. 
  8.  */  
  9. /* 
  10.     child_work为开创的线程实施的函数 
  11.     首要用于等待线程属性状态的扭转,来决断是还是不是有职分要实行 
  12.     而且判定线程的行事情状的变化,来调控参加哪个线程队列(空闲恐怕辛苦) 
  13. */  
  14. void *  
  15. child_work( void *ptr )  
  16. {  
  17.     //这里的ptr为(void *) &temp[i]  
  18.     THREAD_NODE * self = (THREAD_NODE *) ptr;  
  19.   
  20.     /*modify the tid attribute the first time exec */  
  21.     pthread_mutex_lock( &self->mutex );  
  22.     self->tid = syscall( SYS_gettid 卡塔尔(英语:State of Qatar);//获得线程自个儿id  
  23.     pthread_mutex_unlock( &self->mutex );  
  24.   
  25.     while ( 1 )  
  26.     {  
  27.         pthread_mutex_lock( &self->mutex );  
  28.   
  29.         /*if no task exec,blocked */  
  30.         /*  
  31.             关键的一句话 
  32.             从线程的属性struct task_node *work(即为self->work) 
  33.             决断是还是不是已给当下线程分配职务 
  34.         */  
  35.         //借使该线程尚未有分配职务,则透过标准变量窒碍等待条件变量self->cond  
  36.         if ( NULL == self->work )   
  37.         {  
  38.             pthread_cond_wait( &self->cond, &self->mutex );  
  39.         }  
  40.   
  41.         pthread_mutex_lock( &self->work->mutex );  
  42.   
  43.         /*execute the real work.  
  44.             开头试行职分 
  45.         */  
  46.         self->work->fun( self->work->arg );  
  47.   
  48.         /*after finished the work  
  49.             职分实行完后,撤废职务的个性,并销毁职务自己,释放其并吞的财富 
  50.         */  
  51.         self->work->fun       = NULL;  
  52.         self->work->flag  = 0;  
  53.         self->work->tid       = 0;  
  54.         self->work->next  = NULL;  
  55.   
  56.         free( self->work->arg );  
  57.   
  58.         pthread_mutex_unlock( &self->work->mutex ); /* unlock the task */  
  59.         pthread_mutex_destroy( &self->work->mutex );  
  60.   
  61.         /*free the task space */  
  62.         free( self->work );  
  63.   
  64.         /*make self thread no work */  
  65.         self->work   = NULL;  
  66.         self->flag   = 0;  
  67.   
  68.   
  69.         /* 
  70.          * *get new task from the task_link if not NULL. 
  71.          * *there no idle thread if there are task to do. 
  72.          * *if on task ,make self idle and add to the idle queue. 
  73.          */  
  74.         /* 
  75.             实行完上一个职分后,查看任务队列中是不是还会有职分      
  76.         */  
  77.         pthread_mutex_lock( &task_queue_head->mutex );  
  78.         if ( task_queue_head->head != NULL 卡塔尔(英语:State of Qatar)//假诺有职分,则分配职分  
  79.         {  
  80.             TASK_NODE * temp = task_queue_head->head;  
  81.   
  82.             /*get the first task */  
  83.             task_queue_head->head = task_queue_head->head->next;  
  84.   
  85.             /*modify self thread attribute */  
  86.             self->flag   = 1;  
  87.             self->work   = temp;  
  88.             temp->tid    = self->tid;  
  89.             temp->next   = NULL;  
  90.             temp->flag   = 1;  
  91.   
  92.             task_queue_head->number–;  
  93.   
  94.             pthread_mutex_unlock( &task_queue_head->mutex );  
  95.   
  96.             pthread_mutex_unlock( &self->mutex );  
  97.   
  98.             continue;  
  99.         }  
  100.         else //如果未有任务,从艰辛线程队列中删去此线程,将其参加空闲线程队列中    
  101.         {  
  102.             /*no task need to exec, add self to idle queue and del from busy queue */  
  103.             pthread_mutex_unlock( &task_queue_head->mutex );  
  104.   
  105.             pthread_mutex_lock( &pthread_queue_busy->mutex );  
  106.   
  107.             /*self is the last execte thread  
  108.                 假诺此线程是繁忙的线程队列中的仅剩的三个线程 
  109.             */  
  110.             if ( pthread_queue_busy->head == self  
  111.                  && pthread_queue_busy->rear == self )  
  112.             {  
  113.                 pthread_queue_busy->head = pthread_queue_busy->rear = NULL;  
  114.                 self->next           = self->prev = NULL;  
  115.             }  
  116.             /*the first one thread in busy queue  
  117.                 尽管此线程是繁忙的线程队列中的第三个线程 
  118.             */  
  119.             else if ( pthread_queue_busy->head == self  
  120.                   && pthread_queue_busy->rear != self )  
  121.             {  
  122.                 pthread_queue_busy->head = pthread_queue_busy->head->next;  
  123.                 pthread_queue_busy->head->prev    = NULL;  
  124.   
  125.                 self->next = self->prev = NULL;  
  126.             }  
  127.             /*the last one thread in busy queue  
  128.                 假诺此线程是艰巨的线程队列中的末尾的一个线程 
  129.             */  
  130.             else if ( pthread_queue_busy->head != self  
  131.                   && pthread_queue_busy->rear == self )  
  132.             {  
  133.                 pthread_queue_busy->rear = pthread_queue_线程池的相关信息,服务器代码。busy->rear->prev;  
  134.                 pthread_queue_busy->rear->next    = NULL;  
  135.   
  136.                 self->next = self->prev = NULL;  
  137.             }  
  138.             /*middle one  
  139.                 假设此线程是起早摸黑的线程队列中的中间的有些线程 
  140.             */  
  141.             else{  
  142.                 self->next->prev  = self->prev;  
  143.                 self->prev->next  = self->next;  
  144.                 self->next       = self->prev = NULL;  
  145.             }  
  146.   
  147.             pthread_mutex_unlock( &pthread_queue_busy->mutex );  
  148.   
  149.             /*add self to the idle queue  
  150.                 将此线程参预空闲线程队列中 
  151.             */  
  152.             pthread_mutex_lock( &pthread_queue_idle->mutex );  
  153.   
  154.             /*now the idle queue is empty  
  155.                 决断空闲线程队列的场合,依据不一致的动静将此线程参加分裂的地点 
  156.             */  
  157.             if ( pthread_queue_idle->head == NULL  
  158.                  || pthread_queue_idle->rear == NULL )  
  159.             {  
  160.                 pthread_queue_idle->head = pthread_queue_idle->rear = self;  
  161.                 self->next           = self->prev = NULL;  
  162.             }else  {  
  163.                 self->next       = pthread_queue_idle->head;  
  164.                 self->prev       = NULL;  
  165.                 self->next->prev  = self;  
  166.   
  167.                 pthread_queue_idle->head = self;  
  168.                 pthread_queue_idle->number++;  
  169.             }  
  170.   
  171.             pthread_mutex_unlock( &pthread_queue_idle->mutex );  
  172.   
  173.             pthread_mutex_unlock( &self->mutex );  
  174.   
  175.             /*signal have idle thread  
  176.                 告知拥塞等待条件变量pthread_queue_idle->cond的岗位本来就有空闲线程 
  177.             */  
  178.             pthread_cond_signal( &pthread_queue_idle->cond );  
  179.         }  
  180.     }  
  181. }  
  182.   
  183.   
  184. /* 
  185.  * *create thread pool when the system on, and thread number is THREAD_DEF_NUM. 
  186.  * *when init, initial all the thread into a double link queue and all wait fo self->cond. 
  187.  */  
  188. void  
  189. create_pthread_pool( void )  
  190. {  
  191.     //分配线程节点  
  192.     THREAD_NODE * temp =  
  193.         (THREAD_NODE *) malloc( sizeof(THREAD_NODE) * THREAD_DEF_NUM );  
  194.   
  195.     if ( temp == NULL )  
  196.     {  
  197.         printf( ” malloc failuren” );  
  198.         exit( EXIT_FAILURE );  
  199.     }  
  200.   
  201.     /*init as a double link queue  
  202.         开首化为双向链式队列 
  203.     */  
  204.     int i;  
  205.   
  206.     //THREAD_DEF_NUM为线程池中线程的最大数目  
  207.     //for循环带头创立线程池  
  208.     for ( i = 0; i < THREAD_DEF_NUM; i++ )  
  209.     {  
  210.         temp[i].tid     = i + 1;  
  211.         temp[i].work    = NULL;  
  212.         temp[i].flag    = 0;  
  213.   
  214.         if ( i == THREAD_DEF_NUM – 1 )  
  215.             temp[i].next = NULL;  
  216.   
  217.         if ( i == 0 )  
  218.             temp[i].prev = NULL;  
  219.   
  220.         //双向链表的展现  
  221.         temp[i].prev    = &temp[i – 1];  
  222.         temp[i].next    = &temp[i + 1];  
  223.   
  224.         pthread_cond_init( &temp[i].cond, NULL );  
  225.         pthread_mutex_init( &temp[i].mutex, NULL );  
  226.   
  227.         /*create this thread  
  228.             在那创设线程,各样线程实践的函数为child_work 
  229.         */  
  230.         pthread_create( &temp[i].tid, NULL, child_work, (void *) &temp[i] );  
  231.     }  
  232.   
  233.     /*modify the idle thread queue attribute  
  234.         修正空闲线程队列的属性 
  235.     */  
  236.     pthread_mutex_lock( &pthread_queue_idle->mutex );  
  237.   
  238.     pthread_queue_idle->number   = THREAD_DEF_NUM;  
  239.     //此句就将刚成立的那叁个线程给空闲线程队列  
  240.     pthread_queue_idle->head = &temp[0];  
  241.     pthread_queue_idle->rear = &temp[THREAD_DEF_NUM – 1];  
  242.   
  243.     pthread_mutex_unlock( &pthread_queue_idle->mutex );  
  244. }  
  245.   
  246.   
  247. /* 
  248.  * *init_system :init the system glob pointor. 
  249.  */  
  250. void  
  251. init_system( void )  
  252. {  
  253.     /*init the pthread_queue_idle  
  254.         起初化空闲线程队列,接收的是常常的双向链式构造(未循环) 
  255.     */  
  256.     pthread_queue_idle =  
  257.         (PTHREAD_QUEUE_T *) malloc( sizeof(PTHREAD_QUEUE_T) );  
  258.   
  259.     pthread_queue_idle->number   = 0;  
  260.     pthread_queue_idle->head = NULL;  
  261.     pthread_queue_idle->rear = NULL;  
  262.     pthread_mutex_init( &pthread_queue_idle->mutex, NULL );  
  263.     pthread_cond_init( &pthread_queue_idle->cond, NULL );  
  264.   
  265.     /*init the pthread_queue_busy  
  266.         开端化空闲线程队列,采纳的是平凡的双向链式布局(未循环) 
  267.     */  
  268.     pthread_queue_busy =  
  269.         (PTHREAD_QUEUE_T *) malloc( sizeof(PTHREAD_QUEUE_T) );  
  270.   
  271.     pthread_queue_busy->number   = 0;  
  272.     pthread_queue_busy->head = NULL;  
  273.     pthread_queue_busy->rear = NULL;  
  274.     pthread_mutex_init( &pthread_queue_busy->mutex, NULL );  
  275.     pthread_cond_init( &pthread_queue_busy->cond, NULL );  
  276.   
  277.     /*init the task_queue_head  
  278.         起始化职务队列,选用单向链表 
  279.     */  
  280.     task_queue_head = (TASK_QUEUE_T *) malloc( sizeof(TASK_QUEUE_T) );  
  281.   
  282.     task_queue_head->head    = NULL;  
  283.     task_queue_head->number = 0;  
  284.     pthread_cond_init( &task_queue_head->cond, NULL );  
  285.     pthread_mutex_init( &task_queue_head->mutex, NULL );  
  286.   
  287.     /*create thread poll  
  288.         创立线程池 
  289.     */  
  290.     create_pthread_pool();  
  291. }  
  292.   
  293.   
  294. /* 
  295.  * *thread_manager:code exec in manager thread. 
  296.  *               block on task_queue_head->cond when no task come. 
  297.  *               block on pthread_queue_idle->cond when no idle thread 
  298.  **ptr:no used ,in order to avoid warning. 
  299.  **return :nothing. 
  300.  */  
  301.   
  302. void *  
  303. thread_manager( void *ptr )  
  304. {  
  305.     while ( 1 )  
  306.     {  
  307.         THREAD_NODE * temp_thread   = NULL;  
  308.         TASK_NODE   * temp_task = NULL;  
  309.   
  310.         /* 
  311.          * *get a new task, and modify the task_queue. 
  312.          * *if no task block om task_queue_head->cond. 
  313.          */  
  314.         pthread_mutex_lock( &task_queue_head->mutex );  
  315.         //假设职分队列为空,则窒碍等待条件变量task_queue_head->cond  
  316.         if ( task_queue_head->number == 0 )  
  317.             pthread_cond_wait( &task_queue_head->cond,  
  318.                        &task_queue_head->mutex );  
  319.   
  320.         //假如不为空,则始于筹算分配义务,并改进职务队列属性  
  321.         temp_task       = task_queue_head->head;  
  322.         task_queue_head->head    = task_queue_head->head->next;  
  323.         task_queue_head->number–;  
  324.   
  325.         pthread_mutex_unlock( &task_queue_head->mutex );  
  326.   
  327.   
  328.         /* 
  329.          * *get a new idle thread, and modify the idle_queue. 
  330.          * *if no idle thread, block on pthread_queue_idle->cond. 
  331.          */  
  332.         //有了任务之后,起先推断是或不是有空闲线程  
  333.         pthread_mutex_lock( &pthread_queue_idle->mutex );  
  334.           
  335.         //若无空余线程,则堵塞等待条件变量pthread_queue_idle->cond  
  336.         if ( pthread_queue_idle->number == 0 )  
  337.             pthread_cond_wait( &pthread_queue_idle->cond,  
  338.                        &pthread_queue_idle->mutex );  
  339.                          
  340.         //假设有空闲线程则抽取多个悠闲线程,然后改善空闲线程队列属性  
  341.         temp_thread = pthread_queue_idle->head;  
  342.   
  343.         /*if this is the last idle thread ,modiry the head and rear pointor */  
  344.         if ( pthread_queue_idle->head == pthread_queue_idle->rear )  
  345.         {  
  346.             pthread_queue_idle->head = NULL;  
  347.             pthread_queue_idle->rear = NULL;  
  348.         }  
  349.         /*if idle thread number>2, get the first one,modify the head pointor  */  
  350.         else{  
  351.             pthread_queue_idle->head = pthread_queue_idle->head->next;  
  352.             pthread_queue_idle->head->prev    = NULL;  
  353.         }  
  354.   
  355.         pthread_queue_idle->number–;//将空闲线程队列数量减风流倜傥  
  356.   
  357.         pthread_mutex_unlock( &pthread_queue_idle->mutex );  
  358.   
  359.         /*modify the  task attribute.  
  360.             改善收取的线程的线程布局本性和连锁的职责结构属性 
  361.         */  
  362.         pthread_mutex_lock( &temp_task->mutex );  
  363.   
  364.         temp_task->tid   = temp_thread->tid;  
  365.         temp_task->next = NULL;  
  366.         temp_task->flag = 1;  
  367.   
  368.         pthread_mutex_unlock( &temp_task->mutex );  
  369.   
  370.         /*modify the idle thread attribute. */  
  371.         pthread_mutex_lock( &temp_thread->mutex );  
  372.   
  373.         temp_thread->flag    = 1;  
  374.         temp_thread->work    = temp_task;  
  375.         temp_thread->next    = NULL;  
  376.         temp_thread->prev    = NULL;  
  377.   
  378.         pthread_mutex_unlock( &temp_thread->mutex );  
  379.   
  380.         /*add the thread assinged task to the busy queue. */  
  381.         //将已分配任务的线程到场劳顿线程队列中  
  382.         pthread_mutex_lock( &pthread_queue_busy->mutex );  
  383.   
  384.         /*if this is the first one in busy queue */  
  385.         if ( pthread_queue_busy->head == NULL )  
  386.         {  
  387.             pthread_queue_busy->head = temp_thread;  
  388.             pthread_queue_busy->rear = temp_thread;  
  389.             temp_thread->prev        = temp_thread->next = NULL;  
  390.         }else  {  
  391.             /*insert in thre front of the queue */  
  392.             pthread_queue_busy->head->prev    = temp_thread;  
  393.             temp_thread->prev        = NULL;  
  394.             temp_thread->next        = pthread_queue_busy->head;  
  395.             pthread_queue_busy->head = temp_thread;  
  396.             pthread_queue_busy->number++;  
  397.         }  
  398.         pthread_mutex_unlock( &pthread_queue_busy->mutex );  
  399.   
  400.         /*signal the child thread to exec the work */  
  401.         //告知窒碍等待条件变量temp_thread->cond的岗位,早先执行职务  
  402.         pthread_cond_signal( &temp_thread->cond );  
  403.     }  
  404. }  
  405.   
  406.   
  407. /* 
  408.  * *code to process the new client in every chilld pthead. 
  409.  * *ptr: the fd come from listen thread that can communicate to the client. 
  410.  * *return:nothing. void * only used to avoid waring. 
  411.  */  
  412. //用来处理职责的函数  
  413. void *  
  414. prcoess_client( void *ptr )  
  415. {  
  416.     int net_fd;  
  417.     net_fd = atoi( (char *) ptr );  
  418.   
  419.     socklen_t   len;  
  420.     char        buf[MAXBUF + 1];  
  421.     /*下边是select用到的变量的定义 */  
  422.     fd_set      rfds;  
  423.     struct timeval  tv;  
  424.     int     retval;  
  425.     int     maxfd = -1;  
  426.   
  427.     while ( 1 )  
  428.     {  
  429.         FD_ZERO( &rfds );                                                       /* 初始化rfds为空 */  
  430.         FD_SET( 0, &rfds );                                                     /* 将标准输入的描述符0加入到会集rfds中 */  
  431.         FD_SET( net_fd, &rfds );                                                /* 将net_fd出席到群集rfds中 */  
  432.         maxfd       = net_fd + 1;  
  433.         tv.tv_sec   = 1;                                                    /* 窒碍等待时间为1s */  
  434.         tv.tv_usec  = 0;  
  435.   
  436.         retval = select( maxfd, &rfds, NULL, NULL, &tv );                       /* 多路复用,同有的时候候监测描述符0和net_fd */  
  437.         if ( retval == -1 )                                                     /* select函数执行出错 */  
  438.         {  
  439.             perror( “select” );  
  440.             exit( EXIT_FAILURE );  
  441.         }else if ( retval == 0 )                                                /* select函数施行超时 */  
  442.             continue;  
  443.         else{ /*有描述符引起极度 */  
  444.             if ( FD_ISSET( 0, &rfds ) )                                     /* 推断是还是不是行业内部输入0引起的可怜 */  
  445.             {  
  446.                 bzero( buf, sizeof(buf) );                              /* 清空buf */  
  447.                 fgets( buf, sizeof(buf) – 1, stdin );                   /* 从尖峰选拔输入 */  
  448.   
  449.                 if ( !strncasecmp( buf, “quit”, 4 ) )                   /* 判别是或不是为脱离 */  
  450.                 {  
  451.                     printf( “i will close the connect!n” );  
  452.                     close( net_fd );  
  453.                     goto clean;  
  454.                 }  
  455.   
  456.                 len = send( net_fd, buf, strlen( buf ) – 1, 0 );        /* 向客商端发送音信 */  
  457.                 if ( len > 0 )  
  458.                 {  
  459.                     printf( “send successful,%d byte send!n”, len );  
  460.                 }else  {  
  461.                     printf( “message ‘%s’ send failure !n”, buf );  
  462.                     printf( “errno code is %d, errno message is ‘%s’n”, errno, strerror( errno ) );  
  463.                     close( net_fd );  
  464.                     goto clean;  
  465.                 }  
  466.             }  
  467.   
  468.             if ( FD_ISSET( net_fd, &rfds ) )                        /* 判定是还是不是net_fd引起的老大 */  
  469.             {  
  470.                 bzero( buf, sizeof(buf) );  
  471.                 len = recv( net_fd, buf, sizeof(buf) – 1, 0 );  /* 从顾客端选用新闻 */  
  472.                 if ( len > 0 )  
  473.                     printf( “message recv successful : ‘%s’, %d Byte recvn”, buf, len );  
  474.                 else if ( len < 0 )  
  475.                 {  
  476.                     printf( “recv failure !nerrno code is %d, errno message is ‘%s’n”, errno, strerror( errno ) );  
  477.                     close( net_fd );  
  478.                     goto clean;  
  479.                 }else  { /* 如若客商端已关门 */  
  480.                     printf( “the other one close quitn” );  
  481.                     close( net_fd );  
  482.                     return;  
  483.                 }  
  484.             }  
  485.         }  
  486.     }  
  487.     close( net_fd );  
  488.     return;  
  489.   
  490. clean:  
  491.     sys_clean();  
  492. }  
  493.   
  494.   
  495. /* 
  496.  * *task_manager: get new task and add to the tail of the task_link. 
  497.  * *ptr: no used. just avoid warning. 
  498.  * *return:nothing. 
  499.  */  
  500. //用来监听客商端的连接,发生职分  
  501. void *  
  502. task_manager( void *ptr )  
  503. {  
  504.     int listen_fd;  
  505.   
  506.     if ( -1 == (listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) )  
  507.     {  
  508.         perror( “socket” );  
  509.         goto clean;  
  510.     }  
  511.   
  512.     struct ifreq ifr;  
  513.   
  514.     //eno16777736好像于eth0,在Linux系统中得以纠正为eth0  
  515.     strcpy( ifr.ifr_name, “eno16777736” );  
  516.     //获取eno16777736的ip地址  
  517.     if ( ioctl( listen_fd, SIOCGIFADDR, &ifr ) < 0 )  
  518.     {  
  519.         perror( “ioctl” );  
  520.         goto clean;  
  521.     }  
  522.   
  523.     struct sockaddr_in myaddr;  
  524.   
  525.     myaddr.sin_family   = AF_INET;  
  526.     myaddr.sin_port     = htons( PORT 卡塔尔国;//PORT为9001,在头文件中装置,是全局变量  
  527.     myaddr.sin_addr.s_addr  =  
  528.         ( (struct sockaddr_in *) &(ifr.ifr_addr) )->sin_addr.s_addr;  
  529.   
  530. <span style=”white-space:pre”>    </span>//输出ip和port信息  
  531. <span style=”white-space:pre”>    </span>printf(“server_ip = %snserver_port = %dnlisnum = %dn”, inet_ntoa(myaddr.sin_addr), PORT, LISNUM);  
  532.   
  533.     //绑定IP地址和端口port  
  534.     if ( -1 == bind( listen_fd, (struct sockaddr *) &myaddr, sizeof(myaddr) ) )  
  535.     {  
  536.         perror( “bind” );  
  537.         goto clean;  
  538.     }  
  539.     //监听  
  540.     if ( -1 == listen( listen_fd, 5 ) )  
  541.     {  
  542.         perror( “listen” );  
  543.         goto clean;  
  544.     }  
  545.   
  546.     /*i is the id of the task */  
  547.     int i;  
  548.     //伊始接纳顾客端的接连,产生任务  
  549.     for ( i = 1; ; i++ )  
  550.     {  
  551.         int newfd;  
  552.         struct sockaddr_in  client;  
  553.         socklen_t len = sizeof(client);  
  554.   
  555.         if ( -1 ==  
  556.              (newfd = accept( listen_fd, (struct sockaddr *) &client, &len ) ) )  
  557.         {  
  558.             perror( “accept” );  
  559.             goto clean;  
  560.         }  
  561.         /* 打字与印刷此番连接的客商端的地址音信 inet_ntoa  ntohs */  
  562.         printf( “server: got connection from %s, port %d, socket %dn”, inet_ntoa( client.sin_addr ), ntohs( client.sin_port ), newfd );  
  563.   
  564.         //初步将发生的新任务出席职务队列之中  
  565.         TASK_NODE   * temp      = NULL;  
  566.         TASK_NODE   * newtask   = (TASK_NODE *) malloc( sizeof(TASK_NODE) );  
  567.         if ( newtask == NULL )  
  568.         {  
  569.             printf( “malloc error” );  
  570.             goto clean;  
  571.         }  
  572.   
  573.         /* 
  574.          * *initial the attribute of the task. 
  575.          * *because this task havn’t add to system,so,no need lock the mutex. 
  576.          */  
  577.   
  578.         newtask->arg = (void *) malloc( 128 );  
  579.   
  580.         memset( newtask->arg, ‘’, 128 );  
  581.         //职分施行的参数为连续几天来的客户端的socket描述符  
  582.         sprintf( newtask->arg, “%d”, newfd );  
  583.         //新任务的管理函数均为prcoess_client,newfd即为函数prcoess_client的参数  
  584.         newtask->fun     = prcoess_client;  
  585.         newtask->tid     = 0;  
  586.         newtask->work_id = i;  
  587.         newtask->next        = NULL;  
  588.         pthread_mutex_init( &newtask->mutex, NULL );  
  589.   
  590.         /*add new task to task_link */  
  591.         pthread_mutex_lock( &task_queue_head->mutex );  
  592.   
  593.         /*find the tail of the task link and add the new one to tail  
  594.             起始将生出的新义务参加到任务队列中 
  595.         */  
  596.         temp = task_queue_head->head;  
  597.   
  598.         if ( temp == NULL )  
  599.         {  
  600.             task_queue_head->head = newtask;  
  601.         }else  {  
  602.             while ( temp->next != NULL )  
  603.                 temp = temp->next;  
  604.   
  605.             temp->next = newtask;  
  606.         }  
  607.         task_queue_head->number++;//任务队列数量加意气风发  
  608.   
  609.         pthread_mutex_unlock( &task_queue_head->mutex );  
  610.   
  611.         /*signal the manager thread , task coming  
  612.             告知拥塞等待条件变量task_queue_head->cond的职务,本来就有未实行的职分 
  613.         */  
  614.         pthread_cond_signal( &task_queue_head->cond );  
  615.     }  
  616.   
  617.     return;  
  618.   
  619. clean:  
  620.     sys_clean();  
  621. }  
  622.   
  623.   
  624. /* 
  625.  * *monitor: get the system info 
  626.  * *ptr: not used ,only to avoid warning for pthread_create 
  627.  * *return: nothing. 
  628.  */  
  629. //用来输出哪些线程在做事  
  630. void *  
  631. monitor( void *ptr )  
  632. {  
  633.     /*in order to prevent warning. */  
  634.     ptr = ptr;  
  635.   
  636.     THREAD_NODE * temp_thread = NULL;  
  637.   
  638.     while ( 1 )  
  639.     {  
  640.         pthread_mutex_lock( &pthread_queue_busy->mutex );  
  641.   
  642.         /*output the busy thread works one by one */  
  643.         temp_thread = pthread_queue_busy->head;  
  644.   
  645.         printf( “n*******************************n” );  
  646.         while ( temp_thread )  
  647.         {  
  648.             printf( “thread %ld is  execute work_number %dn”,             
  649.                 temp_thread->tid, temp_thread->work->work_id );  
  650.             temp_thread = temp_thread->next;  
  651.         }  
  652.         printf( “*******************************nn” );  
  653.   
  654.         pthread_mutex_unlock( &pthread_queue_busy->mutex );  
  655.   
  656.         sleep( 10 );  
  657.     }  
  658.   
  659.     return;  
  660. }  
  661.   
  662.   
  663. /* 
  664.  * *sys_clean: clean the system . 
  665.  * *this function code need to do to make it more stronger. 
  666.  */  
  667. //清理函数  
  668. void  
  669. sys_clean( void )  
  670. {  
  671.     printf( “the system exit abnormallyn” );  
  672.     exit( EXIT_FAILURE );  
  673. }  

typedef struct {
void *(*function)(void *); /* 函数指针,回调函数 */
void *arg; /* 上面函数的参数 */
} threadpool_task_t; /* 各子线程任务构造体 */

主函数

[cpp] view
plain copy

 print?图片 7图片 8

  1. #include “pthread_pool.h”  
  2.   
  3. //定义多个组织的指针  
  4. PTHREAD_QUEUE_T * pthread_queue_idle;           /* the idle thread double link queue. */  
  5. PTHREAD_QUEUE_T *pthread_queue_busy;            /* the work thread double link queue. */  
  6. TASK_QUEUE_T    *task_queue_head;               /* the task queuee single link list. */  
  7.   
  8. int  
  9. main( int argc, char *argv[] )  
  10. {  
  11.     pthread_t thread_manager_tid, task_manager_tid, monitor_id;  
  12.   
  13.     //起初化空闲线程、在工作线程和要变成的职务  
  14.     init_system();  
  15.   
  16.     //创设线程池管理线程、创制义务处理线程和线程状态监视野程  
  17.     pthread_create( &thread_manager_tid, NULL, thread_manager, NULL );      /* create thread to manage the thread pool. */  
  18.     pthread_create( &task_manager_tid, NULL, task_manager, NULL );          /* create thread recive task from client. */  
  19.     pthread_create( &monitor_id, NULL, monitor, NULL );                     /* create thread to monitor the system info. */  
  20.   
  21.     //等待线程退出  
  22.     pthread_join( thread_manager_tid, NULL );  
  23.     pthread_join( task_manager_tid, NULL );  
  24.     pthread_join( monitor_id, NULL );  
  25.   
  26.     //清理服务器,盘算退出主函数  
  27.     sys_clean();  
  28.   
  29.     return(0);  
  30. }  

/* 描述线程池相关音信 */
struct threadpool_t {
pthread_mutex_t lock; /* 用于锁住本布局体 */
pthread_mutex_t thread_counter; /* 记录忙状态线程个数de琐 —
busy_thr_num */

顾客端代码

[cpp] view
plain copy

 print?图片 9图片 10

  1. /************************************************************************* 
  2.     > File Name: socket_select_client.c 
  3.     > Author: genglut 
  4.     > Mail: genglut@163.com 
  5.     > Created Time: 2014年12月22日 星期一 18时06分06秒 
  6.  ************************************************************************/  
  7.   
  8. #include <stdio.h>  
  9. #include <string.h>  
  10. #include <errno.h>  
  11. #include <sys/socket.h>  
  12. #include <resolv.h>  
  13. #include <stdlib.h>  
  14. #include <netinet/in.h>  
  15. #include <arpa/inet.h>  
  16. #include <unistd.h>  
  17.   
  18. #define MAXBUF 1024  
  19.   
  20. int main(int argc, char *argv[])  
  21. {  
  22.     int sockfd;  
  23.     socklen_t len;  
  24.     struct sockaddr_in server_addr;  
  25.     char buf[MAXBUF + 1];  
  26.   
  27.     //下边是select用到的变量的概念  
  28.     fd_set rfds;  
  29.     struct timeval tv;  
  30.     int retval;  
  31.     int maxfd = -1;  
  32.       
  33.     if(argc != 3)  
  34.     {  
  35.         printf(“error failure, it must be:ntt%s IP port n”, argv[0]);  
  36.         exit(EXIT_FAILURE);  
  37.     }  
  38.   
  39.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  40.     {  
  41.         perror(“socket”);  
  42.         exit(EXIT_FAILURE);  
  43.     }  
  44.   
  45.     bzero(&server_addr, sizeof(server_addr));  
  46.     server_addr.sin_family = AF_INET;  
  47.     server_addr.sin_port = htons(atoi(argv[2]));  
  48.     server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  49.   
  50.     if(connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)  
  51.     {  
  52.         perror(“connect”);  
  53.         exit(EXIT_FAILURE);  
  54.     }  
  55.   
  56.     printf(“already connected to server %sn”, argv[1]);  
  57.       
  58.       
  59.     while(1)  
  60.     {  
  61.         FD_ZERO(&rfds);//初始化rfds为空  
  62.         FD_SET(0, &rfds卡塔尔(قطر‎;//将标准输入的陈诉符0参与到群集rfds中  
  63.         FD_SET(sockfd, &rfds卡塔尔(قطر‎;//将newfd参与到集结rfds中  
  64.         maxfd = sockfd + 1;  
  65.         tv.tv_sec = 1;//拥塞等待时间为1s  
  66.         tv.tv_usec = 0;  
  67.           
  68.         retval = select(maxfd, &rfds, NULL, NULL, &tv卡塔尔(قطر‎;//多路复用,同不时常间监测描述符0和newfd  
  69.           
  70.         if(retval == -1卡塔尔(قطر‎//select函数实行出错  
  71.         {  
  72.             perror(“select”);  
  73.             exit(EXIT_FAILURE);  
  74.         }  
  75.         else if(retval == 0卡塔尔(قطر‎//select函数实施超时  
  76.             continue;  
  77.         else//有描述符引起特别  
  78.         {  
  79.             if(FD_ISSET(0, &rfds卡塔尔(قطر‎卡塔尔(英语:State of Qatar)//判别是或不是行业内部输入0引起的可怜  
  80.             {  
  81.                 bzero(buf, sizeof(buf));//清空buf  
  82.                 fgets(buf, sizeof(buf卡塔尔国-1, stdin卡塔尔;//从终端接纳输入  
  83.   
  84.                 if(!strncasecmp(buf, “quit”, 4卡塔尔卡塔尔国//决断是不是为脱离  
  85.                 {  
  86.                     printf(“i will quit!n”);  
  87.                     break;  
  88.                 }  
  89.                   
  90.                 len = send(sockfd, buf, strlen(buf卡塔尔国-1, 0卡塔尔(英语:State of Qatar);//向客户端发送新闻  
  91.                 if(len > 0)  
  92.                 {  
  93.                     printf (“send successful,%d byte send!n”,len);  
  94.                 }  
  95.                 else  
  96.                 {  
  97.                     printf(“message ‘%s’ send failure !n”, buf);  
  98.                     printf(“errno code is %d, errno message is ‘%s’n”, errno, strerror(errno));  
  99.                     break;  
  100.                 }                     
  101.             }  
  102.               
  103.             if(FD_ISSET(sockfd, &rfds卡塔尔(英语:State of Qatar)卡塔尔(英语:State of Qatar)//推断是还是不是newfd引起的极度  
  104.             {  
  105.                 bzero(buf, sizeof(buf));  
  106.                 len = recv(sockfd, buf, sizeof(buf卡塔尔-1, 0卡塔尔(قطر‎;//从客商端选裁撤息  
  107.                 if(len > 0 )  
  108.                     printf(“message recv successful : ‘%s’, %d Byte recvn”, buf, len);  
  109.                 else if(len < 0)  
  110.                 {  
  111.                     printf(“recv failure !nerrno code is %d, errno message is ‘%s’n”, errno, strerror(errno));  
  112.                     break;  
  113.                 }  
  114.                 else//假设客商端已关闭  
  115.                 {  
  116.                     printf(“the other one close, quitn”);  
  117.                     break;  
  118.                 }                     
  119.             }  
  120.         }     
  121.     }  
  122.       
  123.     close(sockfd);  
  124.     printf(“i quited!n”);  
  125.     return 0;  
  126. }  

pthread_cond_t queue_not_full; /*
当职分队列满时,加多职务的线程窒碍,等待此标准变量 */
pthread_cond_t queue_not_empty; /*
义务队列里不为空时,文告等待任务的线程 */

运行结果

pthread_t *threads; /* 存放线程池中每一种线程的tid。数组 */
pthread_t adjust_tid; /* 存管理线程tid */
threadpool_task_t *task_queue; /* 任务队列(数组首地址卡塔尔国 */

服务器:

[cpp] view
plain copy

 print?图片 11图片 12

  1. $ ./pthread_pool  
  2.   
  3. —————————————–  
  4. —————————————–  
  5.   
  6. server_ip = 172.18.229.60  
  7. server_port = 9001  
  8. lisnum = 5  
  9.   
  10. —————————————–  
  11. —————————————–  
  12.   
  13. server: got connection from 172.18.229.60, port 56023, socket 4  
  14. message recv successful : ‘hello’, 5 Byte recv  
  15.   
  16. —————————————–  
  17. thread 40159 is  execute work_number 1  
  18. —————————————–  
  19.   
  20. server: got connection from 172.18.229.60, port 56024, socket 5  
  21. message recv successful : ‘hi’, 2 Byte recv  
  22. the other one close quit  
  23.   
  24. —————————————–  
  25. thread 40159 is  execute work_number 1  
  26. —————————————–  
  27.   
  28. the other one close quit  

int min_thr_num; /* 线程池最小线程数 */
int max_thr_num; /* 线程池最大线程数 */
int live_thr_num; /* 当前现存线程个数 */
int busy_thr_num; /* 忙状态线程个数 */
int wait_exit_thr_num; /* 要销毁的线程个数 */

客户端1:

[cpp] view
plain copy

 print?图片 13图片 14

  1. $ ./client 172.18.229.60 9001  
  2. already connected to server 172.18.229.60  
  3. hello  
  4. send successful,5 byte send!  
  5. quit  
  6. i will quit!  
  7. i quited!  

int queue_front; /* task_queue队头下标 */
int queue_rear; /* task_queue队尾下标 */
int queue_size; /* task_queue队中实际任务数 */
int queue_max_size; /* task_queue队列可容纳任务数上限 */

客户端2:

[cpp] view
plain copy

 print?图片 15图片 16

  1. $ ./client 172.18.229.60 9001  
  2. already connected to server 172.18.229.60  
  3. hi  
  4. send successful,2 byte send!  
  5. quit  
  6. i will quit!  
  7. i quited!  

int shutdown; /* 标记位,线程池使用途境,true或false */
};

原来的书文链接

============================================

服务器函数试行流程

main

init_system

creat_pthread_pool

child_work

thread_manager

task_manager

process_client

monitor

sys_clean

查阅这段代码的步骤及代码的有关逻辑步骤

Makefile文件

[plain] view
plain copy

 print?图片 17图片 18

  1. CC = gcc  
  2. TARGET = pthread_pool  
  3. SRC = pthread_pool.c base.c  
  4. OBJECT = pthread_pool.o  base.o  
  5. INCLUDES = -I./  
  6. LDFLAGS = -lpthread  
  7.   
  8. all:$(TARGET)  
  9.   
  10. $(OBJECT):$(SRC)  
  11.     $(CC) -c $(INCLUDES) ${SRC}  
  12.   
  13. $(TARGET):$(OBJECT)  
  14.     $(CC) -o $@ $(OBJECT) $(LDFLAGS)  
  15.   
  16. .PHONY:clean  
  17.   
  18. clean:  
  19.     @rm -rf $(OBJECT) $(TARGET) *~  
  1. 大布局体, threadpool_task_t;结构体

  2. main

服务器代码

threadpool_create 创设线程池。

头文件

[cpp] view
plain copy

 print?图片 19图片 20

  1. #ifndef __PTHREAD_POOL_H__  
  2.   
  3. #define __PTHREAD_POOL_H__  
  4.   
  5. #include <stdio.h>  
  6. #include <pthread.h>  
  7. #include <stdlib.h>  
  8. #include <string.h>  
  9. #include <time.h>  
  10. #include <sys/syscall.h>  
  11. #include <sys/types.h>  
  12. #include <unistd.h>  
  13. #include <assert.h>  
  14. #include <sys/stat.h>  
  15. #include <sys/types.h>  
  16. #include <fcntl.h>  
  17. #include <sys/socket.h>  
  18. #include <netinet/in.h>  
  19. #include <arpa/inet.h>  
  20. #include <net/if.h>  
  21. #include <sys/ioctl.h>  
  22. #include <errno.h>  
  23.   
  24. #define THREAD_MAX_NUM  100     /* max number of thread. */  
  25. #define THREAD_DEF_NUM  20      /* by default ,number of thread. */  
  26. #define THREAD_MIN_NUM  5       /* min number of thread pool. */  
  27. #define LISNUM<span style=”white-space:pre”>  </span>5  
  28. #define PORT    9001  
  29. #define MAXBUF  1024  
  30.   
  31.   
  32. /* 
  33.  * *ds of the every task. make all task in a single link 
  34.  */  
  35. //职分结构节点,用于描述各个职务的具体性质  
  36. typedef struct task_node  
  37. {  
  38.     void *arg;                              /* fun arg. */  
  39.     void *(*fun)(void *);                   /* the real work of the task. */  
  40.     pthread_t       tid;            /* which thread exec this task. */  
  41.     int         work_id;        /* task id. */  
  42.     int         flag;           /* 1: assigned, 0: unassigned. */  
  43.     struct task_node    *next;  
  44.     pthread_mutex_t     mutex;          /* when modify this ds and exec the work,lock the task ds. */  
  45. } TASK_NODE;  
  46.   
  47.   
  48. /* 
  49.  * *the ds  of the task_queue 
  50.  */  
  51. //义务队列构造,用于调整总体任务队列  
  52. typedef struct task_queue  
  53. {  
  54.     pthread_mutex_t     mutex;  
  55.     pthread_cond_t      cond;   /* when no task, the manager thread wait for ;when a new task come, signal. */  
  56.     struct task_node    *head;  /* point to the task_link. */  
  57.     int         number; /* current number of task, include unassinged and assigned but no finished. */  
  58. } TASK_QUEUE_T;  
  59.   
  60.   
  61. /* 
  62.  * *the ds of every thread, make all thread in a double link queue. 
  63.  */  
  64. //线程构造节点,用于描述各类线程的现实性质  
  65. typedef struct pthread_node  
  66. {  
  67.     pthread_t       tid;    /* the pid of this thread in kernel,the value is  syscall return . */  
  68.     int         flag;   /*  1:busy, 0:free. */  
  69.     struct task_node    *work;  /*  if exec a work, which work. */  
  70.     struct pthread_node *next;  
  71.     struct pthread_node *prev;  
  72.     pthread_cond_t      cond;   /* when assigned a task, signal this child thread by manager. */  
  73.     pthread_mutex_t     mutex;  
  74. } THREAD_NODE;  
  75.   
  76.   
  77. /* 
  78.  * *the ds of the thread queue 
  79.  */  
  80. //线程队列构造,用于调节空闲线程队列和劳顿线程队列  
  81. typedef struct pthread_queue  
  82. {  
  83.     int         number; /* the number of thread in this queue. */  
  84.     struct pthread_node *head;  
  85.     struct pthread_node *rear;  
  86.     pthread_cond_t      cond;   /* when no idle thread, the manager wait for ,or when a thread return with idle, signal. */  
  87.     pthread_mutex_t     mutex;  
  88. } PTHREAD_QUEUE_T;  
  89.   
  90. //在pthread_poll(卡塔尔国中定义的八个组织的指针  
  91. extern PTHREAD_QUEUE_T  *pthread_queue_idle;    /* the idle thread double link queue. */  
  92. extern PTHREAD_QUEUE_T  *pthread_queue_busy;    /* the work thread double link queue. */  
  93. extern TASK_QUEUE_T *task_queue_head;       /* the task queuee single link list. */  
  94.   
  95. void *child_work( void *ptr );  
  96.   
  97. void create_pthread_pool( void );  
  98.   
  99. void init_system( void );  
  100.   
  101. void *thread_manager( void *ptr );  
  102.   
  103. void *prcoess_client( void *ptr );  
  104.   
  105. void *task_manager( void *ptr );  
  106.   
  107. void *monitor( void *ptr );  
  108.   
  109. void sys_clean( void );  
  110.   
  111. #endif  

for产出任务

基本功函数

[cpp] view
plain copy

 print?图片 21图片 22

  1. #include “pthread_pool.h”  
  2.   
  3.   
  4. /* 
  5.  * *child_work:the code exec in child thread 
  6.  * *ptr: the ds of thread_node of current thread. 
  7.  * *return :nothing.void * just avoid warning. 
  8.  */  
  9. /* 
  10.     child_work为创设的线程实践的函数 
  11.     主要用来等待线程属性状态的更改,来推断是还是不是有职务要实行 
  12.     並且判定线程的职业情形的变型,来支配踏向哪个线程队列(空闲或许劳累) 
  13. */  
  14. void *  
  15. child_work( void *ptr )  
  16. {  
  17.     //这里的ptr为(void *) &temp[i]  
  18.     THREAD_NODE * self = (THREAD_NODE *) ptr;  
  19.   
  20.     /*modify the tid attribute the first time exec */  
  21.     pthread_mutex_lock( &self->mutex );  
  22.     self->tid = syscall( SYS_gettid 卡塔尔(قطر‎;//得到线程自己id  
  23.     pthread_mutex_unlock( &self->mutex );  
  24.   
  25.     while ( 1 )  
  26.     {  
  27.         pthread_mutex_lock( &self->mutex );  
  28.   
  29.         /*if no task exec,blocked */  
  30.         /*  
  31.             关键的一句话 
  32.             从线程的习性struct task_node *work(即为self->work) 
  33.             判定是还是不是已给当下线程分配职分 
  34.         */  
  35.         //要是该线程尚未有分配职责,则通过标准变量拥塞等待条件变量self->cond  
  36.         if ( NULL == self->work )   
  37.         {  
  38.             pthread_cond_wait( &self->cond, &self->mutex );  
  39.         }  
  40.   
  41.         pthread_mutex_lock( &self->work->mutex );  
  42.   
  43.         /*execute the real work.  
  44.             开头实行职务 
  45.         */  
  46.         self->work->fun( self->work->arg );  
  47.   
  48.         /*after finished the work  
  49.             职务实践完后,撤消职分的性质,并销毁职分自己,释放其攻下的财富 
  50.         */  
  51.         self->work->fun       = NULL;  
  52.         self->work->flag  = 0;  
  53.         self->work->tid       = 0;  
  54.         self->work->next  = NULL;  
  55.   
  56.         free( self->work->arg );  
  57.   
  58.         pthread_mutex_unlock( &self->work->mutex ); /* unlock the task */  
  59.         pthread_mutex_destroy( &self->work->mutex );  
  60.   
  61.         /*free the task space */  
  62.         free( self->work );  
  63.   
  64.         /*make self thread no work */  
  65.         self->work   = NULL;  
  66.         self->flag   = 0;  
  67.   
  68.   
  69.         /* 
  70.          * *get new task from the task_link if not NULL. 
  71.          * *there no idle thread if there are task to do. 
  72.          * *if on task ,make self idle and add to the idle queue. 
  73.          */  
  74.         /* 
  75.             执行完上三个职务后,查看任务队列中是否还恐怕有职务      
  76.         */  
  77.         pthread_mutex_lock( &task_queue_head->mutex );  
  78.         if ( task_queue_head->head != NULL 卡塔尔国//假设有任务,则分配职责  
  79.         {  
  80.             TASK_NODE * temp = task_queue_head->head;  
  81.   
  82.             /*get the first task */  
  83.             task_queue_head->head = task_queue_head->head->next;  
  84.   
  85.             /*modify self thread attribute */  
  86.             self->flag   = 1;  
  87.             self->work   = temp;  
  88.             temp->tid    = self->tid;  
  89.             temp->next   = NULL;  
  90.             temp->flag   = 1;  
  91.   
  92.             task_queue_head->number–;  
  93.   
  94.             pthread_mutex_unlock( &task_queue_head->mutex );  
  95.   
  96.             pthread_mutex_unlock( &self->mutex );  
  97.   
  98.             continue;  
  99.         }  
  100.         else //若无任务,从艰辛线程队列中去除此线程,将其进入空闲线程队列中    
  101.         {  
  102.             /*no task need to exec, add self to idle queue and del from busy queue */  
  103.             pthread_mutex_unlock( &task_queue_head->mutex );  
  104.   
  105.             pthread_mutex_lock( &pthread_queue_busy->mutex );  
  106.   
  107.             /*self is the last execte thread  
  108.                 假如此线程是繁忙的线程队列中的仅剩的贰个线程 
  109.             */  
  110.             if ( pthread_queue_busy->head == self  
  111.                  && pthread_queue_busy->rear == self )  
  112.             {  
  113.                 pthread_queue_busy->head = pthread_queue_busy->rear = NULL;  
  114.                 self->next           = self->prev = NULL;  
  115.             }  
  116.             /*the first one thread in busy queue  
  117.                 若是此线程是劳碌的线程队列中的第多少个线程 
  118.             */  
  119.             else if ( pthread_queue_busy->head == self  
  120.                   && pthread_queue_busy->rear != self )  
  121.             {  
  122.                 pthread_queue_busy->head = pthread_queue_busy->head->next;  
  123.                 pthread_queue_busy->head->prev    = NULL;  
  124.   
  125.                 self->next = self->prev = NULL;  
  126.             }  
  127.             /*the last one thread in busy queue  
  128.                 假使此线程是早出晚归的线程队列中的末尾的五个线程 
  129.             */  
  130.             else if ( pthread_queue_busy->head != self  
  131.                   && pthread_queue_busy->rear == self )  
  132.             {  
  133.                 pthread_queue_busy->rear = pthread_queue_busy->rear->prev;  
  134.                 pthread_queue_busy->rear->next    = NULL;  
  135.   
  136.                 self->next = self->prev = NULL;  
  137.             }  
  138.             /*middle one  
  139.                 若是此线程是繁忙的线程队列中的中间的某些线程 
  140.             */  
  141.             else{  
  142.                 self->next->prev  = self->prev;  
  143.                 self->prev->next  = self->next;  
  144.                 self->next       = self->prev = NULL;  
  145.             }  
  146.   
  147.             pthread_mutex_unlock( &pthread_queue_busy->mutex );  
  148.   
  149.             /*add self to the idle queue  
  150.                 将此线程参与空闲线程队列中 
  151.             */  
  152.             pthread_mutex_lock( &pthread_queue_idle->mutex );  
  153.   
  154.             /*now the idle queue is empty  
  155.                 推断空闲线程队列的事态,依据分歧的情况将此线程到场差别的义务 
  156.             */  
  157.             if ( pthread_queue_idle->head == NULL  
  158.                  || pthread_queue_idle->rear == NULL )  
  159.             {  
  160.                 pthread_queue_idle->head = pthread_queue_idle->rear = self;  
  161.                 self->next           = self->prev = NULL;  
  162.             }else  {  
  163.                 self->next       = pthread_queue_idle->head;  
  164.                 self->prev       = NULL;  
  165.                 self->next->prev  = self;  
  166.   
  167.                 pthread_queue_idle->head = self;  
  168.                 pthread_queue_idle->number++;  
  169.             }  
  170.   
  171.             pthread_mutex_unlock( &pthread_queue_idle->mutex );  
  172.   
  173.             pthread_mutex_unlock( &self->mutex );  
  174.   
  175.             /*signal have idle thread  
  176.                 告知窒碍等待条件变量pthread_queue_idle->cond的地点本来就有空闲线程 
  177.             */  
  178.             pthread_cond_signal( &pthread_queue_idle->cond );  
  179.         }  
  180.     }  
  181. }  
  182.   
  183.   
  184. /* 
  185.  * *create thread pool when the system on, and thread number is THREAD_DEF_NUM. 
  186.  * *when init, initial all the thread into a double link queue and all wait fo self->cond. 
  187.  */  
  188. void  
  189. create_pthread_pool( void )  
  190. {  
  191.     //分配线程节点  
  192.     THREAD_NODE * temp =  
  193.         (THREAD_NODE *) malloc( sizeof(THREAD_NODE) * THREAD_DEF_NUM );  
  194.   
  195.     if ( temp == NULL )  
  196.     {  
  197.         printf( ” malloc failuren” );  
  198.         exit( EXIT_FAILURE );  
  199.     }  
  200.   
  201.     /*init as a double link queue  
  202.         开首化为双向链式队列 
  203.     */  
  204.     int i;  
  205.   
  206.     //THREAD_DEF_NUM为线程池中线程的最大数量  
  207.     //for循环开始创造线程池  
  208.     for ( i = 0; i < THREAD_DEF_NUM; i++ )  
  209.     {  
  210.         temp[i].tid     = i + 1;  
  211.         temp[i].work    = NULL;  
  212.         temp[i].flag    = 0;  
  213.   
  214.         if ( i == THREAD_DEF_NUM – 1 )  
  215.             temp[i].next = NULL;  
  216.   
  217.         if ( i == 0 )  
  218.             temp[i].prev = NULL;  
  219.   
  220.         //双向链表的显示  
  221.         temp[i].prev    = &temp[i – 1];  
  222.         temp[i].next    = &temp[i + 1];  
  223.   
  224.         pthread_cond_init( &temp[i].cond, NULL );  
  225.         pthread_mutex_init( &temp[i].mutex, NULL );  
  226.   
  227.         /*create this thread  
  228.             在这里创制线程,种种线程推行的函数为child_work 
  229.         */  
  230.         pthread_create( &temp[i].tid, NULL, child_work, (void *) &temp[i] );  
  231.     }  
  232.   
  233.     /*modify the idle thread queue attribute  
  234.         改革空闲线程队列的属性 
  235.     */  
  236.     pthread_mutex_lock( &pthread_queue_idle->mutex );  
  237.   
  238.     pthread_queue_idle->number   = THREAD_DEF_NUM;  
  239.     //此句就将刚创造的那么些线程给空闲线程队列  
  240.     pthread_queue_idle->head = &temp[0];  
  241.     pthread_queue_idle->rear = &temp[THREAD_DEF_NUM – 1];  
  242.   
  243.     pthread_mutex_unlock( &pthread_queue_idle->mutex );  
  244. }  
  245.   
  246.   
  247. /* 
  248.  * *init_system :init the system glob pointor. 
  249.  */  
  250. void  
  251. init_system( void )  
  252. {  
  253.     /*init the pthread_queue_idle  
  254.         伊始化空闲线程队列,选取的是平日的双向链式布局(未循环) 
  255.     */  
  256.     pthread_queue_idle =  
  257.         (PTHREAD_QUEUE_T *) malloc( sizeof(PTHREAD_QUEUE_T) );  
  258.   
  259.     pthread_queue_idle->number   = 0;  
  260.     pthread_queue_idle->head = NULL;  
  261.     pthread_queue_idle->rear = NULL;  
  262.     pthread_mutex_init( &pthread_queue_idle->mutex, NULL );  
  263.     pthread_cond_init( &pthread_queue_idle->cond, NULL );  
  264.   
  265.     /*init the pthread_queue_busy  
  266.         起头化空闲线程队列,接收的是不足为道的双向链式结构(未循环) 
  267.     */  
  268.     pthread_queue_busy =  
  269.         (PTHREAD_QUEUE_T *) malloc( sizeof(PTHREAD_QUEUE_T) );  
  270.   
  271.     pthread_queue_busy->number   = 0;  
  272.     pthread_queue_busy->head = NULL;  
  273.     pthread_queue_busy->rear = NULL;  
  274.     pthread_mutex_init( &pthread_queue_busy->mutex, NULL );  
  275.     pthread_cond_init( &pthread_queue_busy->cond, NULL );  
  276.   
  277.     /*init the task_queue_head  
  278.         初步化任务队列,选拔单向链表 
  279.     */  
  280.     task_queue_head = (TASK_QUEUE_T *) malloc( sizeof(TASK_QUEUE_T) );  
  281.   
  282.     task_queue_head->head    = NULL;  
  283.     task_queue_head->number = 0;  
  284.     pthread_cond_init( &task_queue_head->cond, NULL );  
  285.     pthread_mutex_init( &task_queue_head->mutex, NULL );  
  286.   
  287.     /*create thread poll  
  288.         创立线程池 
  289.     */  
  290.     create_pthread_pool();  
  291. }  
  292.   
  293.   
  294. /* 
  295.  * *thread_manager:code exec in manager thread. 
  296.  *               block on task_queue_head->cond when no task come. 
  297.  *               block on pthread_queue_idle->cond when no idle thread 
  298.  **ptr:no used ,in order to avoid warning. 
  299.  **return :nothing. 
  300.  */  
  301.   
  302. void *  
  303. thread_manager( void *ptr )  
  304. {  
  305.     while ( 1 )  
  306.     {  
  307.         THREAD_NODE * temp_thread   = NULL;  
  308.         TASK_NODE   * temp_task = NULL;  
  309.   
  310.         /* 
  311.          * *get a new task, and modify the task_queue. 
  312.          * *if no task block om task_queue_head->cond. 
  313.          */  
  314.         pthread_mutex_lock( &task_queue_head->mutex );  
  315.         //假诺职务队列为空,则窒碍等待条件变量task_queue_head->cond  
  316.         if ( task_queue_head->number == 0 )  
  317.             pthread_cond_wait( &task_queue_head->cond,  
  318.                        &task_queue_head->mutex );  
  319.   
  320.         //如果不为空,则开首计划分配任务,并改进职分队列属性  
  321.         temp_task       = task_queue_head->head;  
  322.         task_queue_head->head    = task_queue_head->head->next;  
  323.         task_queue_head->number–;  
  324.   
  325.         pthread_mutex_unlock( &task_queue_head->mutex );  
  326.   
  327.   
  328.         /* 
  329.          * *get a new idle thread, and modify the idle_queue. 
  330.          * *if no idle thread, block on pthread_queue_idle->cond. 
  331.          */  
  332.         //有了职务之后,先导判别是还是不是有空闲线程  
  333.         pthread_mutex_lock( &pthread_queue_idle->mutex );  
  334.           
  335.         //若无空余线程,则窒碍等待条件变量pthread_queue_idle->cond  
  336.         if ( pthread_queue_idle->number == 0 )  
  337.             pthread_cond_wait( &pthread_queue_idle->cond,  
  338.                        &pthread_queue_idle->mutex );  
  339.                          
  340.         //要是有空闲线程则抽取三个悠然线程,然后改过空闲线程队列属性  
  341.         temp_thread = pthread_queue_idle->head;  
  342.   
  343.         /*if this is the last idle thread ,modiry the head and rear pointor */  
  344.         if ( pthread_queue_idle->head == pthread_queue_idle->rear )  
  345.         {  
  346.             pthread_queue_idle->head = NULL;  
  347.             pthread_queue_idle->rear = NULL;  
  348.         }  
  349.         /*if idle thread number>2, get the first one,modify the head pointor  */  
  350.         else{  
  351.             pthread_queue_idle->head = pthread_queue_idle->head->next;  
  352.             pthread_queue_idle->head->prev    = NULL;  
  353.         }  
  354.   
  355.         pthread_queue_idle->number–;//将空闲线程队列数量减风流倜傥  
  356.   
  357.         pthread_mutex_unlock( &pthread_queue_idle->mutex );  
  358.   
  359.         /*modify the  task attribute.  
  360.             改革取出的线程的线程构造本性和有关的职分构造属性 
  361.         */  
  362.         pthread_mutex_lock( &temp_task->mutex );  
  363.   
  364.         temp_task->tid   = temp_thread->tid;  
  365.         temp_task->next = NULL;  
  366.         temp_task->flag = 1;  
  367.   
  368.         pthread_mutex_unlock( &temp_task->mutex );  
  369.   
  370.         /*modify the idle thread attribute. */  
  371.         pthread_mutex_lock( &temp_thread->mutex );  
  372.   
  373.         temp_thread->flag    = 1;  
  374.         temp_thread->work    = temp_task;  
  375.         temp_thread->next    = NULL;  
  376.         temp_thread->prev    = NULL;  
  377.   
  378.         pthread_mutex_unlock( &temp_thread->mutex );  
  379.   
  380.         /*add the thread assinged task to the busy queue. */  
  381.         //将已分配职分的线程参加辛劳线程队列中  
  382.         pthread_mutex_lock( &pthread_queue_busy->mutex );  
  383.   
  384.         /*if this is the first one in busy queue */  
  385.         if ( pthread_queue_busy->head == NULL )  
  386.         {  
  387.             pthread_queue_busy->head = temp_thread;  
  388.             pthread_queue_busy->rear = temp_thread;  
  389.             temp_thread->prev        = temp_thread->next = NULL;  
  390.         }else  {  
  391.             /*insert in thre front of the queue */  
  392.             pthread_queue_busy->head->prev    = temp_thread;  
  393.             temp_thread->prev        = NULL;  
  394.             temp_thread->next        = pthread_queue_busy->head;  
  395.             pthread_queue_busy->head = temp_thread;  
  396.             pthread_queue_busy->number++;  
  397.         }  
  398.         pthread_mutex_unlock( &pthread_queue_busy->mutex );  
  399.   
  400.         /*signal the child thread to exec the work */  
  401.         //告知拥塞等待条件变量temp_thread->cond的地点,开首实施职责  
  402.         pthread_cond_signal( &temp_thread->cond );  
  403.     }  
  404. }  
  405.   
  406.   
  407. /* 
  408.  * *code to process the new client in every chilld pthead. 
  409.  * *ptr: the fd come from listen thread that can communicate to the client. 
  410.  * *return:nothing. void * only used to avoid waring. 
  411.  */  
  412. //用来拍卖职分的函数  
  413. void *  
  414. prcoess_client( void *ptr )  
  415. {  
  416.     int net_fd;  
  417.     net_fd = atoi( (char *) ptr );  
  418.   
  419.     socklen_t   len;  
  420.     char        buf[MAXBUF + 1];  
  421.     /*下边是select用到的变量的定义 */  
  422.     fd_set      rfds;  
  423.     struct timeval  tv;  
  424.     int     retval;  
  425.     int     maxfd = -1;  
  426.   
  427.     while ( 1 )  
  428.     {  
  429.         FD_ZERO( &rfds );                                                       /* 初始化rfds为空 */  
  430.         FD_SET( 0, &rfds );                                                     /* 将标准输入的叙说符0出席到集结rfds中 */  
  431.         FD_SET( net_fd, &rfds );                                                /* 将net_fd加入到集合rfds中 */  
  432.         maxfd       = net_fd + 1;  
  433.         tv.tv_sec   = 1;                                                    /* 窒碍等待时间为1s */  
  434.         tv.tv_usec  = 0;  
  435.   
  436.         retval = select( maxfd, &rfds, NULL, NULL, &tv );                       /* 多路复用,同时监测描述符0和net_fd */  
  437.         if ( retval == -1 )                                                     /* select函数实践出错 */  
  438.         {  
  439.             perror( “select” );  
  440.             exit( EXIT_FAILURE );  
  441.         }else if ( retval == 0 )                                                /* select函数试行超时 */  
  442.             continue;  
  443.         else{ /*有描述符引起极其 */  
  444.             if ( FD_ISSET( 0, &rfds ) )                                     /* 判别是或不是明媒正娶输入0引起的不胜 */  
  445.             {  
  446.                 bzero( buf, sizeof(buf) );                              /* 清空buf */  
  447.                 fgets( buf, sizeof(buf) – 1, stdin );                   /* 从极限采用输入 */  
  448.   
  449.                 if ( !strncasecmp( buf, “quit”, 4 ) )                   /* 推断是或不是为脱离 */  
  450.                 {  
  451.                     printf( “i will close the connect!n” );  
  452.                     close( net_fd );  
  453.                     goto clean;  
  454.                 }  
  455.   
  456.                 len = send( net_fd, buf, strlen( buf ) – 1, 0 );        /* 向顾客端发送新闻 */  
  457.                 if ( len > 0 )  
  458.                 {  
  459.                     printf( “send successful,%d byte send!n”, len );  
  460.                 }else  {  
  461.                     printf( “message ‘%s’ send failure !n”, buf );  
  462.                     printf( “errno code is %d, errno message is ‘%s’n”, errno, strerror( errno ) );  
  463.                     close( net_fd );  
  464.                     goto clean;  
  465.                 }  
  466.             }  
  467.   
  468.             if ( FD_ISSET( net_fd, &rfds ) )                        /* 推断是或不是net_fd引起的极其 */  
  469.             {  
  470.                 bzero( buf, sizeof(buf) );  
  471.                 len = recv( net_fd, buf, sizeof(buf) – 1, 0 );  /* 从客商端接纳音信 */  
  472.                 if ( len > 0 )  
  473.                     printf( “message recv successful : ‘%s’, %d Byte recvn”, buf, len );  
  474.                 else if ( len < 0 )  
  475.                 {  
  476.                     printf( “recv failure !nerrno code is %d, errno message is ‘%s’n”, errno, strerror( errno ) );  
  477.                     close( net_fd );  
  478.                     goto clean;  
  479.                 }else  { /* 假若客商端已关闭 */  
  480.                     printf( “the other one close quitn” );  
  481.                     close( net_fd );  
  482.                     return;  
  483.                 }  
  484.             }  
  485.         }  
  486.     }  
  487.     close( net_fd );  
  488.     return;  
  489.   
  490. clean:  
  491.     sys_clean();  
  492. }  
  493.   
  494.   
  495. /* 
  496.  * *task_manager: get new task and add to the tail of the task_link. 
  497.  * *ptr: no used. just avoid warning. 
  498.  * *return:nothing. 
  499.  */  
  500. //用来监听顾客端的一而再一连,发生职分  
  501. void *  
  502. task_manager( void *ptr )  
  503. {  
  504.     int listen_fd;  
  505.   
  506.     if ( -1 == (listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) )  
  507.     {  
  508.         perror( “socket” );  
  509.         goto clean;  
  510.     }  
  511.   
  512.     struct ifreq ifr;  
  513.   
  514.     //eno16777736看似于eth0,在Linux系统中得以改过为eth0  
  515.     strcpy( ifr.ifr_name, “eno16777736” );  
  516.     //获取eno16777736的ip地址  
  517.     if ( ioctl( listen_fd, SIOCGIFADDR, &ifr ) < 0 )  
  518.     {  
  519.         perror( “ioctl” );  
  520.         goto clean;  
  521.     }  
  522.   
  523.     struct sockaddr_in myaddr;  
  524.   
  525.     myaddr.sin_family   = AF_INET;  
  526.     myaddr.sin_port     = htons( PORT 卡塔尔(قطر‎;//PORT为9001,在头文件中安装,是全局变量  
  527.     myaddr.sin_addr.s_addr  =  
  528.         ( (struct sockaddr_in *) &(ifr.ifr_addr) )->sin_addr.s_addr;  
  529.   
  530. <span style=”white-space:pre”>    </span>//输出ip和port信息  
  531. <span style=”white-space:pre”>    </span>printf(“server_ip = %snserver_port = %dnlisnum = %dn”, inet_ntoa(myaddr.sin_addr), PORT, LISNUM);  
  532.   
  533.     //绑定IP地址和端口port  
  534.     if ( -1 == bind( listen_fd, (struct sockaddr *) &myaddr, sizeof(myaddr) ) )  
  535.     {  
  536.         perror( “bind” );  
  537.         goto clean;  
  538.     }  
  539.     //监听  
  540.     if ( -1 == listen( listen_fd, 5 ) )  
  541.     {  
  542.         perror( “listen” );  
  543.         goto clean;  
  544.     }  
  545.   
  546.     /*i is the id of the task */  
  547.     int i;  
  548.     //开端选择客户端的连接,产生职责  
  549.     for ( i = 1; ; i++ )  
  550.     {  
  551.         int newfd;  
  552.         struct sockaddr_in  client;  
  553.         socklen_t len = sizeof(client);  
  554.   
  555.         if ( -1 ==  
  556.              (newfd = accept( listen_fd, (struct sockaddr *) &client, &len ) ) )  
  557.         {  
  558.             perror( “accept” );  
  559.             goto clean;  
  560.         }  
  561.         /* 打字与印刷此次连接的客户端的地点信息 inet_ntoa  ntohs */  
  562.         printf( “server: got connection from %s, port %d, socket %dn”, inet_ntoa( client.sin_addr ), ntohs( client.sin_port ), newfd );  
  563.   
  564.         //起初将爆发的新职分插足义务队列之中  
  565.         TASK_NODE   * temp      = NULL;  
  566.         TASK_NODE   * newtask   = (TASK_NODE *) malloc( sizeof(TASK_NODE) );  
  567.         if ( newtask == NULL )  
  568.         {  
  569.             printf( “malloc error” );  
  570.             goto clean;  
  571.         }  
  572.   
  573.         /* 
  574.          * *initial the attribute of the task. 
  575.          * *because this task havn’t add to system,so,no need lock the mutex. 
  576.          */  
  577.   
  578.         newtask->arg = (void *) malloc( 128 );  
  579.   
  580.         memset( newtask->arg, ‘’, 128 );  
  581.         //职责奉行的参数为总是的顾客端的socket描述符  
  582.         sprintf( newtask->arg, “%d”, newfd );  
  583.         //新任务的管理函数均为prcoess_client,newfd即为函数prcoess_client的参数  
  584.         newtask->fun     = prcoess_client;  
  585.         newtask->tid     = 0;  
  586.         newtask->work_id = i;  
  587.         newtask->next        = NULL;  
  588.         pthread_mutex_init( &newtask->mutex, NULL );  
  589.   
  590.         /*add new task to task_link */  
  591.         pthread_mutex_lock( &task_queue_head->mutex );  
  592.   
  593.         /*find the tail of the task link and add the new one to tail  
  594.             最初将生出的新职务参加到任务队列中 
  595.         */  
  596.         temp = task_queue_head->head;  
  597.   
  598.         if ( temp == NULL )  
  599.         {  
  600.             task_queue_head->head = newtask;  
  601.         }else  {  
  602.             while ( temp->next != NULL )  
  603.                 temp = temp->next;  
  604.   
  605.             temp->next = newtask;  
  606.         }  
  607.         task_queue_head->number++;//任务队列数量加意气风发  
  608.   
  609.         pthread_mutex_unlock( &task_queue_head->mutex );  
  610.   
  611.         /*signal the manager thread , task coming  
  612.             告知窒碍等待条件变量task_queue_head->cond的职位,原来就有未实行的职分 
  613.         */  
  614.         pthread_cond_signal( &task_queue_head->cond );  
  615.     }  
  616.   
  617.     return;  
  618.   
  619. clean:  
  620.     sys_clean();  
  621. }  
  622.   
  623.   
  624. /* 
  625.  * *monitor: get the system info 
  626.  * *ptr: not used ,only to avoid warning for pthread_create 
  627.  * *return: nothing. 
  628.  */  
  629. //用来输出哪些线程在做事  
  630. void *  
  631. monitor( void *ptr )  
  632. {  
  633.     /*in order to prevent warning. */  
  634.     ptr = ptr;  
  635.   
  636.     THREAD_NODE * temp_thread = NULL;  
  637.   
  638.     while ( 1 )  
  639.     {  
  640.         pthread_mutex_lock( &pthread_queue_busy->mutex );  
  641.   
  642.         /*output the busy thread works one by one */  
  643.         temp_thread = pthread_queue_busy->head;  
  644.   
  645.         printf( “n*******************************n” );  
  646.         while ( temp_thread )  
  647.         {  
  648.             printf( “thread %ld is  execute work_number %dn”,             
  649.                 temp_thread->tid, temp_thread->work->work_id );  
  650.             temp_thread = temp_thread->next;  
  651.         }  
  652.         printf( “*******************************nn” );  
  653.   
  654.         pthread_mutex_unlock( &pthread_queue_busy->mutex );  
  655.   
  656.         sleep( 10 );  
  657.     }  
  658.   
  659.     return;  
  660. }  
  661.   
  662.   
  663. /* 
  664.  * *sys_clean: clean the system . 
  665.  * *this function code need to do to make it more stronger. 
  666.  */  
  667. //清理函数  
  668. void  
  669. sys_clean( void )  
  670. {  
  671.     printf( “the system exit abnormallyn” );  
  672.     exit( EXIT_FAILURE );  
  673. }  

threadpool_add 加多任务。

主函数

[cpp] view
plain copy

 print?图片 23图片 24

  1. #include “pthread_pool.h”  
  2.   
  3. //定义多少个布局的指针  
  4. PTHREAD_QUEUE_T * pthread_queue_idle;           /* the idle thread double link queue. */  
  5. PTHREAD_QUEUE_T *pthread_queue_busy;            /* the work thread double link queue. */  
  6. TASK_QUEUE_T    *task_queue_head;               /* the task queuee single link list. */  
  7.   
  8. int  
  9. main( int argc, char *argv[] )  
  10. {  
  11.     pthread_t thread_manager_tid, task_manager_tid, monitor_id;  
  12.   
  13.     //带头化空闲线程、在职业线程和要成功的天职  
  14.     init_system();  
  15.   
  16.     //成立线程池管理线程、成立职责管理线程和线程状态监视野程  
  17.     pthread_create( &thread_manager_tid, NULL, thread_manager, NULL );      /* create thread to manage the thread pool. */  
  18.     pthread_create( &task_manager_tid, NULL, task_manager, NULL );          /* create thread recive task from client. */  
  19.     pthread_create( &monitor_id, NULL, monitor, NULL );                     /* create thread to monitor the system info. */  
  20.   
  21.     //等待线程退出  
  22.     pthread_join( thread_manager_tid, NULL );  
  23.     pthread_join( task_manager_tid, NULL );  
  24.     pthread_join( monitor_id, NULL );  
  25.   
  26.     //清理服务器,准备退出主函数  
  27.     sys_clean();  
  28.   
  29.     return(0);  
  30. }  

销毁线程池。

顾客端代码

[cpp] view
plain copy

 print?图片 25图片 26

  1. /************************************************************************* 
  2.     > File Name: socket_select_client.c 
  3.     > Author: genglut 
  4.     > Mail: genglut@163.com 
  5.     > Created Time: 2014年12月22日 星期一 18时06分06秒 
  6.  ************************************************************************/  
  7.   
  8. #include <stdio.h>  
  9. #include <string.h>  
  10. #include <errno.h>  
  11. #include <sys/socket.h>  
  12. #include <resolv.h>  
  13. #include <stdlib.h>  
  14. #include <netinet/in.h>  
  15. #include <arpa/inet.h>  
  16. #include <unistd.h>  
  17.   
  18. #define MAXBUF 1024  
  19.   
  20. int main(int argc, char *argv[])  
  21. {  
  22.     int sockfd;  
  23.     socklen_t len;  
  24.     struct sockaddr_in server_addr;  
  25.     char buf[MAXBUF + 1];  
  26.   
  27.     //下边是select用到的变量的概念  
  28.     fd_set rfds;  
  29.     struct timeval tv;  
  30.     int retval;  
  31.     int maxfd = -1;  
  32.       
  33.     if(argc != 3)  
  34.     {  
  35.         printf(“error failure, it must be:ntt%s IP port n”, argv[0]);  
  36.         exit(EXIT_FAILURE);  
  37.     }  
  38.   
  39.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  40.     {  
  41.         perror(“socket”);  
  42.         exit(EXIT_FAILURE);  
  43.     }  
  44.   
  45.     bzero(&server_addr, sizeof(server_addr));  
  46.     server_addr.sin_family = AF_INET;  
  47.     server_addr.sin_port = htons(atoi(argv[2]));  
  48.     server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  49.   
  50.     if(connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)  
  51.     {  
  52.         perror(“connect”);  
  53.         exit(EXIT_FAILURE);  
  54.     }  
  55.   
  56.     printf(“already connected to server %sn”, argv[1]);  
  57.       
  58.       
  59.     while(1)  
  60.     {  
  61.         FD_ZERO(&rfds);//初始化rfds为空  
  62.         FD_SET(0, &rfds卡塔尔(قطر‎;//将正式输入的叙说符0到场到会集rfds中  
  63.         FD_SET(sockfd, &rfds卡塔尔;//将newfd参加到集合rfds中  
  64.         maxfd = sockfd + 1;  
  65.         tv.tv_sec = 1;//堵塞等待时间为1s  
  66.         tv.tv_usec = 0;  
  67.           
  68.         retval = select(maxfd, &rfds, NULL, NULL, &tv卡塔尔(英语:State of Qatar);//多路复用,同期监测描述符0和newfd  
  69.           
  70.         if(retval == -1卡塔尔//select函数实施出错  
  71.         {  
  72.             perror(“select”);  
  73.             exit(EXIT_FAILURE);  
  74.         }  
  75.         else if(retval == 0卡塔尔(英语:State of Qatar)//select函数试行超时  
  76.             continue;  
  77.         else//有描述符引起特别  
  78.         {  
  79.             if(FD_ISSET(0, &rfds卡塔尔(英语:State of Qatar)卡塔尔(قطر‎//推断是否标准输入0引起的丰富  
  80.             {  
  81.                 bzero(buf, sizeof(buf));//清空buf  
  82.                 fgets(buf, sizeof(buf卡塔尔(قطر‎-1, stdin卡塔尔(قطر‎;//从尖峰选用输入  
  83.   
  84.                 if(!strncasecmp(buf, “quit”, 4卡塔尔(قطر‎卡塔尔国//推断是还是不是为洗脱  
  85.                 {  
  86.                     printf(“i will quit!n”);  
  87.                     break;  
  88.                 }  
  89.                   
  90.                 len = send(sockfd, buf, strlen(buf卡塔尔-1, 0卡塔尔(英语:State of Qatar);//向顾客端发送新闻  
  91.                 if(len > 0)  
  92.                 {  
  93.                     printf (“send successful,%d byte send!n”,len);  
  94.                 }  
  95.                 else  
  96.                 {  
  97.                     printf(“message ‘%s’ send failure !n”, buf);  
  98.                     printf(“errno code is %d, errno message is ‘%s’n”, errno, strerror(errno));  
  99.                     break;  
  100.                 }                     
  101.             }  
  102.               
  103.             if(FD_ISSET(sockfd, &rfds卡塔尔卡塔尔//判别是或不是newfd引起的那二个  
  104.             {  
  105.                 bzero(buf, sizeof(buf));  
  106.                 len = recv(sockfd, buf, sizeof(buf卡塔尔-1, 0卡塔尔;//从客商端选择音信  
  107.                 if(len > 0 )  
  108.                     printf(“message recv successful : ‘%s’, %d Byte recvn”, buf, len);  
  109.                 else if(len < 0)  
  110.                 {  
  111.                     printf(“recv failure !nerrno code is %d, errno message is ‘%s’n”, errno, strerror(errno));  
  112.                     break;  
  113.                 }  
  114.                 else//若是客户端已关门  
  115.                 {  
  116.                     printf(“the other one close, quitn”);  
  117.                     break;  
  118.                 }                     
  119.             }  
  120.         }     
  121.     }  
  122.       
  123.     close(sockfd);  
  124.     printf(“i quited!n”);  
  125.     return 0;  
  126. }  
  1. threadpool_create()

  2. threadpool_thread()

运作结果

跟踪到pthread_cond_wait();阻塞

服务器:

[cpp] view
plain copy

 print?图片 27图片 28

  1. $ ./pthread_pool  
  2.   
  3. —————————————–  
  4. —————————————–  
  5.   
  6. server_ip = 172.18.229.60  
  7. server_port = 9001  
  8. lisnum = 5  
  9.   
  10. —————————————–  
  11. —————————————–  
  12.   
  13. server: got connection from 172.18.229.60, port 56023, socket 4  
  14. message recv successful : ‘hello’, 5 Byte recv  
  15.   
  16. —————————————–  
  17. thread 40159 is  execute work_number 1  
  18. —————————————–  
  19.   
  20. server: got connection from 172.18.229.60, port 56024, socket 5  
  21. message recv successful : ‘hi’, 2 Byte recv  
  22. the other one close quit  
  23.   
  24. —————————————–  
  25. thread 40159 is  execute work_number 1  
  26. —————————————–  
  27.   
  28. the other one close quit  
  1. threadpool_add()

客户端1:

[cpp] view
plain copy

 print?图片 29图片 30

  1. $ ./client 172.18.229.60 9001  
  2. already connected to server 172.18.229.60  
  3. hello  
  4. send successful,5 byte send!  
  5. quit  
  6. i will quit!  
  7. i quited!  

跟踪到pthread_cond_signal(); 会到4步中
pthread_cond_wait()继续向后。

客户端2:

[cpp] view
plain copy

 print?图片 31图片 32

  1. $ ./client 172.18.229.60 9001  
  2. already connected to server 172.18.229.60  
  3. hi  
  4. send successful,2 byte send!  
  5. quit  
  6. i will quit!  
  7. i quited!  
  1. adjust_thread()

初藳链接

添加10个线程

移除10个线程 —pthread_exit();

  1. threadpool_destroy()

销毁线程池。 —pthread_exit();

 

标签:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图