1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <semaphore.h>
5 #include <unistd.h>
6 #include <time.h>
7 #include <sys/types.h>
8 #include <pthread.h>
9 #define bool int
10 #define true 1
11 #define false 0
12 #define rerange BF_rerange//选择内存分配方法
13 #define schedule fifo//选择调度方法
14 #define THREAD_MAXN 2//线程数
15 #define RUNTIME_SUB 1//每次运行线程减去的运行时间
16 #define INIT_FREE_BLOCK_NUM 8//内存块初始数量
17 #define INIT_FREE_BLOCK_SIZE 10//内存块初始大小
18 #define FREE_MAXN 80//最大空闲块数量
19 #define RUN_TIME 10000//线程运行时间
20 #define STU_NUM 10000//学生数量
21 //-----结构体定义
22 typedef struct TCB//存储线程信息
23 {
24 int thread_id;//线程编号
25 int arriveTime;//线程到达时间
26 int runTime;//持续时间
27 int finishTime;//完成时间
28 int wholeTime;//周转时间
29 double weightWholeTime;//带权周转时间
30 bool Finished;//线程是否完成
31 struct TCB* next;//使用链式存储方式
32 }TCB;
33 struct task
34 {
35 void *(*task_func) (void *param);
36 void *param;
37 struct task *next;
38 };
39 struct tcb_queue//TCB队列定义
40 {
41 struct TCB* tcbQueue[THREAD_MAXN+1];//TCB指针数组
42 int r, f;
43 };
44 struct thread_pool//线程池结构体
45 {
46 pthread_mutex_t tcb_lock;//互斥锁
47 int fDestroyed;//线程池是否被销毁
48 pthread_t* threadid;//存储线程标识符指针
49 struct TCB* nowRunThread;//指向当前正在运行的线程
50 int nFinish;//完成线程数
51 sem_t sem[THREAD_MAXN+1];//用于控制线程的信号量
52 struct tcb_queue rrQueue;//轮转队列
53 struct tcb_queue showQueue;//用于辅助打印的队列
54 struct task *task_queue;//任务队列
55 int task_num;
56 struct TCB* tcb;//存储TCB
57 };
58 struct free_block//空闲块结构体
59 {
60 int start;//起始位置
61 int size;
62 struct free_block* next;
63 };
64 struct busy_block//被分配的内存块
65 {
66 int id;//编号
67 int start;
68 int size;
69 char* data;//根据需要动态分配
70 struct busy_block* next;
71 };
72 struct student//储存学生信息
73 {
74 char number[9];
75 char name[76];
76 int name_size;
77 };
78 //-----全局变量定义
79 static struct thread_pool* pool = NULL;//全局变量pool,指向线程池
80 int nowTime;//当前已走过的时间
81 int busy_cnt = -1;//分配块编号计数器
82 int nFree = 0;//空闲块数量
83 int nBusy = 0;//已分配块数量
84 int nameCnt = 0;//名字存储计数器
85 int numCnt = 0;//学号存储计数器
86 int ScheduleCnt = 0;//调度次数
87 struct free_block* free_queue = NULL;//储存空闲块的链表
88 struct busy_block* busy_queue = NULL;//储存已分配块的链表
89 struct student student_info[STU_NUM];
90 //-----函数声明
91 void TCB_bubble();//给TCB排序
92 void add_task (void *(*task_func)(void *param));
93 void show_rr();//打印轮转队列
94 void show_tcb();//打印所有线程的信息
95 void pool_init();//初始化线程池
96 void* thread_run_func(void* param);//线程里运行的函数
97 void round_robin();//时间片轮转算法的调度函数
98 int pool_destroy();//销毁线程池
99 void init_free();//初始化空闲块
100 struct free_block* create_free(int start, int size, struct free_block* next);//创建一个空闲块
101 struct busy_block* create_busy(int start, int size, struct busy_block* next, char* data);//创建一个已分配块
102 struct free_block* merge_free(struct free_block* f);//合并所有能够合并的空闲内存块
103 void init_student();//初始化学生的学号,姓名,采用随机生成的方法
104 void insert_busy(struct busy_block* pBusy);//尾插法插入一个分配块到链表busy_queue中
105 void insert_free(struct free_block* pFree);//尾插法插入一个空闲块到链表free_queue中
106 void delete_free(struct free_block* pFree, int size);//删除一个空闲块中被占用的部分,保留剩余部分
107 void fifo_delete_busy();//fifo算法中删除分配块
108 void lifo_delete_busy();//lifo算法中删除分配块
109 void show_free();//显示空闲块链表
110 void show_busy();//显示分配块链表
111 void free_bubble(int choice);//choice1:start升序,choice2:size升序,choice3:size降序
112 void FF_rerange();//按不同内存分配方法的规则排序
113 void BF_rerange();
114 void WF_rerange();
115 void *store_info(void* param);//param: 1存学号,2存姓名
116 void merge_in();//合并空闲内存块函数的入口
117 void fifo();//fifo算法调出分配块
118 void lifo();//lifo算法调出分配块
119 void enqueue(struct tcb_queue *q, struct TCB* tcb);
120 struct TCB* dequeue(struct tcb_queue *q);
121 struct TCB* get_front(struct tcb_queue *q);
122 bool empty(struct tcb_queue *q);
123 //main
124 int main()
125 {
126 init_student();
127 init_free();
128 pool_init();
129 TCB_bubble();
130 show_tcb();
131 for(int i = 0; i < 2*STU_NUM; ++i) add_task(store_info);
132 round_robin();
133 sleep(3);
134 pool_destroy();
135 return 0;
136 }
137 //函数定义
138 void TCB_bubble()//给TCB排序,按arriveTime升序排列
139 {
140 TCB* ptemp = NULL;
141 for (int i = 0; i < THREAD_MAXN+1; ++i)
142 {
143 ptemp = pool->tcb;
144 int f = 0;
145 while (ptemp && ptemp->next)
146 {
147 if (ptemp->arriveTime > ptemp->next->arriveTime)
148 {//交换两个节点
149 f = 1;
150 TCB* p_next = ptemp->next->next;
151 TCB* p_pre = ptemp;//后面ptemp = ptemp->next,当前ptemp相当于pre
152 TCB* p_pre_pre = pool->tcb;//pre的pre
153 if (p_pre_pre == p_pre)//说明ptemp是头结点
154 {
155 p_pre_pre = NULL;
156 }
157 else//否则找到pre_pre所在位置
158 {
159 while (p_pre_pre && p_pre_pre->next != p_pre)
160 {
161 p_pre_pre = p_pre_pre->next;
162 }
163 }
164 //交换结点
165 ptemp = ptemp->next;
166 ptemp->next = p_pre;
167 p_pre->next = p_next;
168 if (p_pre_pre)
169 {
170 p_pre_pre->next = ptemp;
171 }
172 else
173 {
174 pool->tcb = ptemp;
175 }
176 }
177 ptemp = ptemp->next;
178 }
179 if(f == 0) return;
180 }
181 }
182 void show_rr()//打印轮转队列
183 {
184 printf("当前时间为:%d
", nowTime);
185 if (pool->rrQueue.f == pool->rrQueue.r)
186 {
187 printf("目前还没有线程到达
");
188 }
189 else
190 {
191 printf("目前轮转队列为:
");
192 }
193 while (!empty(&(pool->rrQueue)))
194 {
195 enqueue(&(pool->showQueue), get_front(&(pool->rrQueue)));
196 printf("%d ", dequeue(&(pool->rrQueue))->thread_id);
197 }
198 while (!empty(&(pool->showQueue)))//将队列放回
199 {
200 enqueue(&(pool->rrQueue), dequeue(&(pool->showQueue)));
201 }
202 printf("
");
203 }
204 void show_tcb()//打印所有线程的信息
205 {
206 TCB* ptemp = pool->tcb;
207 printf("打印所有线程的信息:
");
208 while (ptemp)
209 {
210 printf("线程%d:到达时间:%d,剩余时间:%d
", ptemp->thread_id, ptemp->arriveTime, ptemp->runTime);
211 ptemp = ptemp->next;
212 }
213 printf("
");
214 }
215 void pool_init()//初始化线程池
216 {
217 pool = (struct thread_pool*)malloc(sizeof(struct thread_pool));
218 pthread_mutex_init(&(pool->tcb_lock), NULL);//初始为未锁住状态
219 pool->fDestroyed = 0;//线程池是否被销毁
220 pool->nFinish = 0;
221 pool->task_num = 0;
222 pool->nowRunThread = NULL;//指向当前正在运行的线程
223 pool->rrQueue.f = pool->rrQueue.r = 0;//轮转队列
224 pool->showQueue.r = pool->showQueue.r = 0;//用于辅助打印的队列
225 pool->task_queue = NULL;
226 pool->tcb = NULL;
227 //创建并初始化TCB
228 TCB* ptemp = pool->tcb;
229 srand(time(0));
230 for (int i = 0; i < THREAD_MAXN; ++i)
231 {
232 TCB* s = (TCB*)malloc(sizeof(TCB));
233 // s->arriveTime = rand()%9;
234 s->arriveTime = 0;
235 s->runTime = RUN_TIME;
236 s->thread_id = i;//编号令为0
237 s->Finished = false;
238 s->next = NULL;
239 //尾插入
240 if (!pool->tcb)//第一个节点
241 {
242 pool->tcb = s;
243 }
244 else
245 {
246 ptemp = pool->tcb;
247 while (ptemp && ptemp->next)
248 {
249 ptemp = ptemp->next;
250 }
251 ptemp->next = s;
252 }
253 }
254 //初始化信号量
255 ptemp = pool->tcb;
256 int i = 0;
257 while (ptemp)
258 {
259 int i = ptemp->thread_id;
260 sem_init(&(pool->sem[i]), 0, 0);
261 ptemp = ptemp->next;
262 }
263 //创建线程
264 ptemp = pool->tcb;
265 pool->threadid = (pthread_t*)malloc(sizeof(pthread_t) * (THREAD_MAXN+1));
266 while (ptemp)
267 {
268 //把ptemp作为参数传入thread_run_func()
269 int t;
270 t = pthread_create(&(pool->threadid[ptemp->thread_id]),
271 NULL, thread_run_func, ptemp);
272 if (!t)//线程创建成功
273 {
274 printf("线程%d创建成功!
", ptemp->thread_id);
275 }
276 else
277 {
278 printf("线程创建失败!
");
279 }
280 ptemp = ptemp->next;
281 }
282 printf("线程池pool初始化完成!
");
283 }
284 void* thread_run_func(void* param)//线程里运行的函数
285 {
286 TCB* ptemp = (TCB*)param;
287 int i = 0;
288 while (ptemp->runTime > 0)
289 {
290 sem_wait(&(pool->sem[ptemp->thread_id]));//唤醒
291 pthread_mutex_lock(&(pool->tcb_lock));//上互斥锁
292 if (pool->fDestroyed)
293 {
294 pthread_mutex_unlock(&(pool->tcb_lock));
295 printf ("线程%d退出
", ptemp->thread_id);
296 pthread_exit (NULL);
297 }
298 ptemp->runTime -= RUNTIME_SUB;
299 //线程操作
300 printf("当前线程:%d号
", ptemp->thread_id);
301 struct task *pTask = pool->task_queue;
302 if(pool->task_queue)
303 {
304 pool->task_queue = pool->task_queue->next;
305 --pool->task_num;
306 }
307 else
308 {
309 pthread_mutex_unlock(&(pool->tcb_lock));
310 printf("任务为空
");
311 break;
312 }
313 if (ptemp->thread_id == 0)i = 1;//number
314 else i = 2;
315 (*(pTask->task_func))(&i);
316
317 free(pTask);
318 pTask = NULL;
319 //线程操作
320 if (ptemp->runTime <= 0)//线程已经完成
321 {
322 ++pool->nFinish;
323 ptemp->Finished = true;
324 //出队
325 dequeue(&(pool->rrQueue));
326 }
327 else
328 {//还未完成
329 //出队
330 dequeue(&(pool->rrQueue));
331 //入队
332 enqueue(&(pool->rrQueue), ptemp);
333 }
334 pthread_mutex_unlock(&(pool->tcb_lock));
335 sleep(1);
336 }
337 pthread_exit(NULL);
338 }
339 void round_robin()//时间片轮转算法的调度函数
340 {
341 TCB* ptemp = pool->tcb;
342 while (1)
343 {
344 //sleep(1);
345 pthread_mutex_lock(&(pool->tcb_lock));
346 if (pool->nFinish == THREAD_MAXN)//所有线程完成
347 break;
348 while (ptemp && ptemp->arriveTime == nowTime)
349 {
350 enqueue(&(pool->rrQueue), ptemp);
351 ptemp = ptemp->next;
352 }
353 if (pool->rrQueue.f != pool->rrQueue.r)
354 {
355 pool->nowRunThread = get_front(&(pool->rrQueue));
356 sem_post(&(pool->sem[pool->nowRunThread->thread_id]));
357 }
358 ++nowTime;
359 pthread_mutex_unlock(&(pool->tcb_lock));
360 sleep(1);
361 }
362 }
363 int pool_destroy()//销毁线程池
364 {
365 if (pool->fDestroyed)//防止重复销毁
366 return -1;
367 pool->fDestroyed = 1;
368 TCB* ptemp = pool->tcb;
369 while (ptemp)
370 {
371 pthread_join(pool->threadid[ptemp->thread_id], NULL);
372 printf("线程%d已结束
", ptemp->thread_id);
373 ptemp = ptemp->next;
374 }
375 free(ptemp);
376 free(pool->threadid);
377 pthread_mutex_destroy(&(pool->tcb_lock));
378 free(pool);
379 pool = NULL;
380 printf("线程池pool已被销毁!
");
381 return 0;
382 }
383
384 //----------------------------------------------------------------------------------
385
386 void init_free()
387 {
388 int start_address = 0;
389 struct free_block* ptemp = NULL;
390 for (int i = 0; i < INIT_FREE_BLOCK_NUM; ++i)
391 {
392 struct free_block* s = create_free(start_address, INIT_FREE_BLOCK_SIZE, NULL);
393 printf("已创建起始地址为%d,大小为%d的空闲块!
", s->start, s->size);
394 ++nFree;
395 if (!free_queue)
396 {
397 free_queue = s;
398 }
399 else
400 {
401 ptemp = free_queue;
402 while (ptemp && ptemp->next)
403 {
404 ptemp = ptemp->next;
405 }
406 ptemp->next = s;
407 }
408 start_address += INIT_FREE_BLOCK_SIZE;
409 }
410 printf("空闲内存块初始化完成!
");
411 show_free();
412 }
413 struct free_block* create_free(int start, int size, struct free_block* next)
414 {
415 struct free_block* s = (struct free_block*)malloc(sizeof(struct free_block));
416 s->start = start;
417 s->size = size;
418 s->next = next;
419 return s;
420 }
421 struct busy_block* create_busy(int start, int size, struct busy_block* next, char* data)
422 {
423 struct busy_block* s = (struct busy_block*)malloc(sizeof(struct busy_block));
424 s->start = start;
425 s->id = ++busy_cnt;
426 s->next = NULL;
427 s->size = size;
428 s->data = (char*)malloc(sizeof(char) * size);
429 for (int i = 0; i < size; ++i)
430 {
431 s->data[i] = data[i];
432 }
433 return s;
434 }
435 void init_student()
436 {
437 srand(time(0));
438 for (int i = 0; i < STU_NUM; ++i)
439 {
440 strcpy(student_info[i].number, "18");
441 for(int j=2; j<8; ++j)
442 {
443 student_info[i].number[j] = (char)('0'+(rand()%10));
444 }
445 student_info[i].number[8] = '