1. 程式人生 > 實用技巧 >執行緒池+時間片輪轉法排程+連續記憶體管理+記憶體排程

執行緒池+時間片輪轉法排程+連續記憶體管理+記憶體排程

  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 THREAD_MAXN 100//執行緒數 13 #define RUNTIME_SUB 1//每次執行執行緒減去的執行時間 14 #define RUN_TIME 100//執行緒執行時間 15 #define TASK_NUM 10000//任務數 16 //-----結構體定義 17 typedef struct TCB//儲存執行緒資訊 18 { 19 int thread_id;//執行緒編號 20 int arriveTime;//執行緒到達時間 21 int runTime;//持續時間 22 int finishTime;//完成時間 23 int wholeTime;//
週轉時間 24 double weightWholeTime;//帶權週轉時間 25 bool Finished;//執行緒是否完成 26 struct TCB* next;//使用鏈式儲存方式 27 }TCB; 28 struct TCB_counterpart 29 { 30 struct TCB *father; 31 struct TCB_counterpart *next; 32 }; 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 TCB_counterpart *nowPullQueue; 55 struct task *task_queue;//任務佇列 56 int task_num; 57 struct TCB* tcb;//儲存TCB 58 }; 59 //-----全域性變數定義 60 static struct thread_pool* pool = NULL;//全域性變數pool,指向執行緒池 61 int nowTime = -1;//當前已走過的時間 62 //-----函式宣告 63 void TCB_bubble();//給TCB排序 64 void add_task (void *(*task_func)(void *param)); 65 void task_init(); 66 void show_rr();//列印輪轉佇列 67 void show_tcb();//列印所有執行緒的資訊 68 void pool_init();//初始化執行緒池 69 void* thread_run_func(void* param);//執行緒裡執行的函式 70 void round_robin();//時間片輪轉演算法的排程函式 71 int pool_destroy();//銷燬執行緒池 72 void* task_run(); 73 void pull_thread(); 74 void enqueue(struct tcb_queue *q, struct TCB* tcb); 75 struct TCB* dequeue(struct tcb_queue *q); 76 struct TCB* get_front(struct tcb_queue *q); 77 bool empty(struct tcb_queue *q); 78 struct TCB_counterpart* create_TCB_counterpart(); 79 void insert_counterpart(struct TCB *tcb); 80 //main 81 int main() 82 { 83 pool_init(); 84 TCB_bubble(); 85 show_tcb(); 86 task_init(); 87 round_robin(); 88 sleep(3); 89 pool_destroy(); 90 return 0; 91 } 92 //函式定義 93 void TCB_bubble()//給TCB排序,按arriveTime升序排列 94 { 95 TCB* ptemp = NULL; 96 for (int i = 0; i < THREAD_MAXN+1; ++i) 97 { 98 ptemp = pool->tcb; 99 int f = 0; 100 while (ptemp && ptemp->next) 101 { 102 if (ptemp->arriveTime > ptemp->next->arriveTime) 103 {//交換兩個節點 104 f = 1; 105 TCB* p_next = ptemp->next->next; 106 TCB* p_pre = ptemp;//後面ptemp = ptemp->next,當前ptemp相當於pre 107 TCB* p_pre_pre = pool->tcb;//pre的pre 108 if (p_pre_pre == p_pre)//說明ptemp是頭結點 109 { 110 p_pre_pre = NULL; 111 } 112 else//否則找到pre_pre所在位置 113 { 114 while (p_pre_pre && p_pre_pre->next != p_pre) 115 { 116 p_pre_pre = p_pre_pre->next; 117 } 118 } 119 //交換結點 120 ptemp = ptemp->next; 121 ptemp->next = p_pre; 122 p_pre->next = p_next; 123 if (p_pre_pre) 124 { 125 p_pre_pre->next = ptemp; 126 } 127 else 128 { 129 pool->tcb = ptemp; 130 } 131 } 132 ptemp = ptemp->next; 133 } 134 if(f == 0) return; 135 } 136 } 137 void show_rr()//列印輪轉佇列 138 { 139 if (empty(&(pool->rrQueue))) 140 { 141 printf("目前還沒有執行緒在佇列中\n"); 142 } 143 else 144 { 145 printf("目前輪轉佇列為:\n"); 146 } 147 while (!empty(&(pool->rrQueue))) 148 { 149 enqueue(&(pool->showQueue), get_front(&(pool->rrQueue))); 150 printf("%d ", dequeue(&(pool->rrQueue))->thread_id); 151 } 152 while (!empty(&(pool->showQueue)))//將佇列放回 153 { 154 enqueue(&(pool->rrQueue), dequeue(&(pool->showQueue))); 155 } 156 printf("\n"); 157 } 158 void show_tcb()//列印所有執行緒的資訊 159 { 160 TCB* ptemp = pool->tcb; 161 printf("列印所有執行緒的資訊:\n"); 162 while (ptemp) 163 { 164 printf("執行緒%d:到達時間:%d,剩餘時間:%d\n", ptemp->thread_id, ptemp->arriveTime, ptemp->runTime); 165 ptemp = ptemp->next; 166 } 167 printf("\n"); 168 } 169 void pool_init()//初始化執行緒池 170 { 171 pool = (struct thread_pool*)malloc(sizeof(struct thread_pool)); 172 pthread_mutex_init(&(pool->tcb_lock), NULL);//初始為未鎖住狀態 173 pool->fDestroyed = 0;//執行緒池是否被銷燬 174 pool->nFinish = 0; 175 pool->task_num = 0; 176 pool->nowRunThread = NULL;//指向當前正在執行的執行緒 177 pool->rrQueue.f = pool->rrQueue.r = 0;//輪轉佇列 178 pool->showQueue.r = pool->showQueue.r = 0;//用於輔助列印的佇列 179 pool->task_queue = NULL; 180 pool->nowPullQueue = NULL; 181 pool->tcb = NULL; 182 //建立並初始化TCB 183 TCB* ptemp = pool->tcb; 184 srand(time(0)); 185 for (int i = 0; i < THREAD_MAXN; ++i) 186 { 187 TCB* s = (TCB*)malloc(sizeof(TCB)); 188 // s->arriveTime = rand()%9; 189 s->arriveTime = 0; 190 s->runTime = RUN_TIME; 191 s->thread_id = i;//編號令為0 192 s->Finished = false; 193 s->next = NULL; 194 //尾插入 195 if (!pool->tcb)//第一個節點 196 { 197 pool->tcb = s; 198 } 199 else 200 { 201 ptemp = pool->tcb; 202 while (ptemp && ptemp->next) 203 { 204 ptemp = ptemp->next; 205 } 206 ptemp->next = s; 207 } 208 } 209 //初始化訊號量 210 ptemp = pool->tcb; 211 int i = 0; 212 while (ptemp) 213 { 214 int i = ptemp->thread_id; 215 sem_init(&(pool->sem[i]), 0, 0); 216 ptemp = ptemp->next; 217 } 218 //建立執行緒 219 ptemp = pool->tcb; 220 pool->threadid = (pthread_t*)malloc(sizeof(pthread_t) * (THREAD_MAXN+1)); 221 while (ptemp) 222 { 223 //把ptemp作為引數傳入thread_run_func() 224 int t; 225 t = pthread_create(&(pool->threadid[ptemp->thread_id]), \ 226 NULL, thread_run_func, ptemp); 227 if (!t)//執行緒建立成功 228 { 229 printf("執行緒%d建立成功!\n", ptemp->thread_id); 230 } 231 else 232 { 233 printf("執行緒建立失敗!\n"); 234 } 235 ptemp = ptemp->next; 236 } 237 printf("執行緒池pool初始化完成!\n"); 238 } 239 void* thread_run_func(void* param)//執行緒裡執行的函式 240 { 241 TCB* ptemp = (TCB*)param; 242 while (ptemp->runTime > 0) 243 { 244 sem_wait(&(pool->sem[ptemp->thread_id]));//喚醒 245 pthread_mutex_lock(&(pool->tcb_lock));//上互斥鎖 246 if (pool->fDestroyed) 247 { 248 pthread_mutex_unlock(&(pool->tcb_lock)); 249 printf ("執行緒%d退出\n", ptemp->thread_id); 250 pthread_exit (NULL); 251 } 252 ptemp->runTime -= RUNTIME_SUB; 253 if(ptemp->runTime > 0) enqueue(&(pool->rrQueue), ptemp); 254 printf("執行緒%d(剩餘時間%d->%d)", ptemp->thread_id, ptemp->runTime + RUNTIME_SUB, ptemp->runTime < 0 ? 0 : ptemp->runTime); 255 //執行緒操作 256 struct task *pTask = pool->task_queue; 257 if(pool->task_queue) 258 { 259 pool->task_queue = pool->task_queue->next; 260 --pool->task_num; 261 } 262 else 263 { 264 pthread_mutex_unlock(&(pool->tcb_lock)); 265 printf("任務為空\n"); 266 break; 267 } 268 (*(pTask->task_func))(pTask->param); 269 free(pTask); 270 pTask = NULL; 271 pthread_mutex_unlock(&(pool->tcb_lock)); 272 sleep(1); 273 } 274 pthread_exit(NULL); 275 } 276 void round_robin()//時間片輪轉演算法的排程函式 277 { 278 TCB* ptemp = pool->tcb; 279 while (1) 280 { 281 ++nowTime; 282 pthread_mutex_lock(&(pool->tcb_lock)); 283 if (pool->nFinish == THREAD_MAXN)//所有執行緒完成 284 break; 285 while (ptemp && ptemp->arriveTime == nowTime) 286 { 287 printf("當前時間為%d, 執行緒%d進入輪轉佇列,執行時間:%d\n",nowTime, ptemp->thread_id, ptemp->runTime); 288 enqueue(&(pool->rrQueue), ptemp); 289 ptemp=ptemp->next; 290 } 291 printf("\n"); 292 show_rr(); 293 pull_thread(); 294 pthread_mutex_unlock(&(pool->tcb_lock)); 295 sleep(10); 296 if(!pool->task_queue)break; 297 } 298 } 299 int pool_destroy()//銷燬執行緒池 300 { 301 if (pool->fDestroyed)//防止重複銷燬 302 return -1; 303 pool->fDestroyed = 1; 304 TCB* ptemp = pool->tcb; 305 while (ptemp) 306 { 307 pthread_join(pool->threadid[ptemp->thread_id], NULL); 308 printf("執行緒%d已結束\n", ptemp->thread_id); 309 ptemp = ptemp->next; 310 } 311 struct task *ptask = pool->task_queue; 312 while (pool->task_queue) 313 { 314 ptask = pool->task_queue; 315 pool->task_queue = pool->task_queue->next; 316 free(ptask); 317 } 318 free(ptemp); 319 free(pool->threadid); 320 pthread_mutex_destroy(&(pool->tcb_lock)); 321 free(pool); 322 pool = NULL; 323 printf("執行緒池pool已被銷燬!\n"); 324 return 0; 325 } 326 void* task_run() 327 { 328 printf("正在執行任務\n"); 329 sleep(1); 330 return; 331 } 332 void add_task(void *(*task_func)(void *param)) 333 { 334 pthread_mutex_lock(&(pool->tcb_lock)); 335 struct task *newtask = (struct task*) malloc (sizeof (struct task)); 336 newtask->task_func = task_run;//要執行的函式 337 newtask->next = NULL; 338 struct task *pTask = pool->task_queue; 339 if (pTask) 340 { 341 while (pTask && pTask->next) 342 pTask = pTask->next; 343 pTask->next = newtask; 344 } 345 else 346 { 347 pool->task_queue = newtask; 348 } 349 ++pool->task_num; 350 pthread_mutex_unlock(&(pool->tcb_lock)); 351 return; 352 } 353 void task_init() 354 { 355 for(int i = 0; i < TASK_NUM; ++i) 356 add_task(task_run); 357 } 358 void pull_thread() 359 { 360 struct TCB *ptemp1 = NULL; 361 struct TCB *ptemp2 = NULL; 362 struct TCB *ptemp3 = NULL; 363 if(pool->nowPullQueue) 364 { 365 struct nowPullQueue *ppull = pool->nowPullQueue; 366 while(pool->nowPullQueue) 367 { 368 ppull = pool->nowPullQueue; 369 pool->nowPullQueue = pool->nowPullQueue->next; 370 free(ppull); 371 } 372 pool->nowPullQueue = NULL; 373 } 374 printf("當前時間為:%d,輪轉的執行緒為:",nowTime); 375 if(!empty(&(pool->rrQueue))) 376 { 377 ptemp1 = dequeue(&(pool->rrQueue)); 378 sem_post(&(pool->sem[ptemp1->thread_id])); 379 insert_counterpart(ptemp1); 380 sleep(2); 381 if(!empty(&(pool->rrQueue))) 382 { 383 ptemp2 = dequeue(&(pool->rrQueue)); 384 sem_post(&(pool->sem[ptemp2->thread_id])); 385 insert_counterpart(ptemp2); 386 sleep(2); 387 if(!empty(&(pool->rrQueue))) 388 { 389 ptemp3 = dequeue(&(pool->rrQueue)); 390 sem_post(&(pool->sem[ptemp3->thread_id])); 391 insert_counterpart(ptemp3); 392 sleep(2); 393 } 394 } 395 } 396 printf("\n"); 397 } 398 void enqueue(struct tcb_queue *q, struct TCB* tcb) 399 { 400 q->r = (q->r + 1) % (THREAD_MAXN+1); 401 q->tcbQueue[q->r] = tcb; 402 } 403 struct TCB* dequeue(struct tcb_queue *q) 404 { 405 q->f = (q->f + 1) % (THREAD_MAXN+1); 406 return q->tcbQueue[q->f]; 407 } 408 struct TCB* get_front(struct tcb_queue *q) 409 { 410 return q->tcbQueue[(q->f + 1) % (THREAD_MAXN+1)]; 411 } 412 bool empty(struct tcb_queue *q) 413 { 414 return q->r == q->f; 415 } 416 struct TCB_counterpart* create_TCB_counterpart() 417 { 418 struct TCB_counterpart *s = (struct TCB_counterpart*)malloc(sizeof(struct TCB_counterpart)); 419 s->next = NULL; 420 s->father = NULL; 421 return s; 422 } 423 void insert_counterpart(struct TCB *tcb) 424 { 425 if(!pool->nowPullQueue) 426 { 427 pool->nowPullQueue = create_TCB_counterpart(); 428 pool->nowPullQueue->father = tcb; 429 } 430 else 431 { 432 struct TCB_counterpart *ptemp = pool->nowPullQueue; 433 while(ptemp && ptemp->next) 434 { 435 ptemp = ptemp->next; 436 } 437 ptemp->next = create_TCB_counterpart(); 438 ptemp->next->father = tcb; 439 } 440 }
執行緒池

  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\n", nowTime);
185     if (pool->rrQueue.f == pool->rrQueue.r)
186     {
187         printf("目前還沒有執行緒到達\n");
188     }
189     else
190     {
191         printf("目前輪轉佇列為:\n");
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("\n\n");
203 }
204 void show_tcb()//列印所有執行緒的資訊
205 {
206     TCB* ptemp = pool->tcb;
207     printf("列印所有執行緒的資訊:\n");
208     while (ptemp)
209     {
210         printf("執行緒%d:到達時間:%d,剩餘時間:%d\n", ptemp->thread_id, ptemp->arriveTime, ptemp->runTime);
211         ptemp = ptemp->next;
212     }
213     printf("\n");
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建立成功!\n", ptemp->thread_id);
275         }
276         else
277         {
278             printf("執行緒建立失敗!\n");
279         }
280         ptemp = ptemp->next;
281     }
282     printf("執行緒池pool初始化完成!\n");
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退出\n", ptemp->thread_id);
296             pthread_exit (NULL);
297         }
298         ptemp->runTime -= RUNTIME_SUB;
299         //執行緒操作
300         printf("當前執行緒:%d號\n", 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("任務為空\n");
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已結束\n", 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已被銷燬!\n");
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的空閒塊!\n", 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("空閒記憶體塊初始化完成!\n");
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] = '\0';
446         student_info[i].name_size = 4 + (rand() % 70);//拼音長度:4~20
447         for (int j = 0; j < student_info[i].name_size; ++j)
448         {
449             student_info[i].name[j] = (char)('a' + rand()%26);
450         }
451         student_info[i].name[student_info[i].name_size] = '\0';
452         printf("編號:%d,姓名:%s,姓名大小:%d,學號:%s\n", i, student_info[i].name, student_info[i].name_size, student_info[i].number);
453     }
454     printf("學生資訊初始化完成!\n");
455 }
456 void free_bubble(int choice)
457 {
458     struct free_block* ptemp = NULL;
459     if (free_queue)
460         for (int i = 0; i < FREE_MAXN; ++i)
461         {
462             int fReturn = 0;
463             ptemp = free_queue;
464             while (ptemp && ptemp->next)
465             {
466                 if ((ptemp->start > ptemp->next->start && choice == 1) || /*FF*/
467                     (ptemp->size > ptemp->next->size && choice == 2) || /*BF*/
468                     (ptemp->size < ptemp->next->size && choice == 3) ) /*WF*/ 
469                 {//交換兩個節點
470                     fReturn = 1;
471                     struct free_block* p_next = ptemp->next->next;
472                     struct free_block* p_pre = ptemp;
473                     struct free_block* p_pre_pre = free_queue;
474                     if (p_pre_pre == p_pre)
475                     {
476                         p_pre_pre = NULL;
477                     }
478                     else
479                     {
480                         while (p_pre_pre && p_pre_pre->next != p_pre)
481                         {
482                             p_pre_pre = p_pre_pre->next;
483                         }
484                     }
485                     ptemp = ptemp->next;
486                     ptemp->next = p_pre;
487                     p_pre->next = p_next;
488                     if (p_pre_pre)
489                     {
490                         p_pre_pre->next = ptemp;
491                     }
492                     else
493                     {
494                         free_queue = ptemp;
495                     }
496                 }
497                 ptemp = ptemp->next;
498             }
499             if(fReturn == 0)//排序已完成
500             {
501                 return;
502             }
503         }
504 }
505 void insert_busy(struct busy_block* pBusy)
506 {
507     if (!busy_queue)
508     {
509         busy_queue = pBusy;
510     }
511     else
512     {
513         struct busy_block* ptemp = busy_queue;
514         while (ptemp && ptemp->next)
515         {
516             ptemp = ptemp->next;
517         }
518         ptemp->next = pBusy;
519     }
520     ++nBusy;
521     printf("完成插入分配塊——開始地址:%d,大小:%d\n", pBusy->start, pBusy->size);
522     return;
523 }
524 void insert_free(struct free_block* pFree)
525 {
526     if (!free_queue)
527     {
528         free_queue = pFree;
529     }
530     else
531     {
532         struct free_block* ptemp = free_queue;
533         while (ptemp && ptemp->next)
534         {
535             ptemp = ptemp->next;
536         }
537         ptemp->next = pFree;
538     }
539     ++nFree;
540     printf("完成插入空閒塊——開始地址:%d,大小:%d\n", pFree->start, pFree->size);
541     return;
542 }
543 void delete_free(struct free_block* pFree, int size)
544 {
545     if (!free_queue)return;
546     struct free_block* ptemp = free_queue;
547     struct free_block* pre = NULL;
548     while (ptemp)
549     {
550         if (ptemp == pFree)
551         {
552             if (pre)
553             {
554                 if (pFree->size == size)//無剩餘
555                 {
556                     --nFree;
557                     pre->next = ptemp->next;
558                 }
559                 else
560                 {
561                     pre->next = create_free(pFree->start + size, pFree->size - size, ptemp->next);
562                 }
563             }
564             else
565             {
566                 if (pFree->size == size)
567                 {
568                     free_queue = ptemp->next;
569                 }
570                 else
571                 {
572                     free_queue = create_free(pFree->start + size, pFree->size - size, ptemp->next);
573                 }
574             }
575             free(ptemp);
576             ptemp = NULL;
577             break;
578         }
579         pre = ptemp;
580         ptemp = ptemp->next;
581     }
582     return;
583 }
584 void fifo_delete_busy()
585 {
586     if (busy_queue)
587     {
588         struct busy_block* ptemp = busy_queue;
589         busy_queue = busy_queue->next;
590         free(ptemp);
591         ptemp = NULL;
592         --nBusy;
593     }
594     else
595     {
596         printf("無分配塊\n");
597     }
598 }
599 void lifo_delete_busy()
600 {
601     if (busy_queue)
602     {
603         struct busy_block* ptemp = busy_queue;
604         struct busy_block* pre = NULL;
605         while (ptemp && ptemp->next)
606         {
607             pre = ptemp;
608             ptemp = ptemp->next;
609         }
610         if (!pre)
611         {
612             busy_queue = NULL;
613         }
614         else
615         {
616             pre->next = NULL;
617         }
618         free(ptemp);
619         ptemp = NULL;
620         --nBusy;
621     }
622     else
623     {
624         printf("無分配塊\n");
625     }
626     return;
627 }
628 void show_free()
629 {
630     if (free_queue)
631     {
632         struct free_block* ptemp = free_queue;
633         printf("顯示空閒塊:\n");
634         while (ptemp)
635         {
636             printf("————開始:%d,大小:%d\n", ptemp->start, ptemp->size);
637             ptemp = ptemp->next;
638         }
639         printf("\n");
640     }
641     else
642     {
643         printf("當前無空閒塊\n");
644     }
645     return;
646 }
647 void show_busy()
648 {
649     if (busy_queue)
650     {
651         struct busy_block* ptemp = busy_queue;
652         printf("顯示已分配塊:\n");
653         while (ptemp)
654         {
655             printf("—————————序號:%d,開始:%d,大小:%d,資料:", ptemp->id, ptemp->start, ptemp->size);
656             for (int i = 0; i < ptemp->size; ++i)
657             {
658                 printf("%c", ptemp->data[i]);
659             }
660             printf("\n");
661             ptemp = ptemp->next;
662         }
663         printf("\n");
664     }
665     else
666     {
667         printf("當前無分配塊\n");
668     }
669     return;
670 }
671 void merge_in()
672 {
673     free_bubble(1);
674     free_queue = merge_free(free_queue);
675     printf("緊縮完成\n");
676     return;
677 }
678 struct free_block* merge_free(struct free_block* f)
679 {
680     if (f && f->next)
681     {
682         f->next = merge_free(f->next);
683         if (f->next && (f->start + f->size == f->next->start))
684         {
685             struct free_block* p = f->next;
686             f->next = p->next;
687             f->size += p->size;
688             free(p);
689             p = NULL;
690         }
691     }
692     return f;
693 }
694 void fifo()
695 {
696     if (busy_queue)
697     {
698         printf("+++++++++++++++++++++被調出的資訊:序號:%d,開始地址:%d,大小:%d, 資料:", \
699             busy_queue->id, busy_queue->start, busy_queue->size);
700         for (int k = 0; k < busy_queue->size; ++k)
701         {
702             printf("%c", busy_queue->data[k]);
703         }
704         printf("\n");
705         printf("+++++++++++++++++++++排程次數:%d\n", ++ScheduleCnt);
706         struct free_block* pFree = create_free(busy_queue->start, busy_queue->size, NULL);
707         insert_free(pFree);
708         fifo_delete_busy();
709     }
710     else
711     {
712         printf("無分配塊,無法調出\n");
713     }
714     return;
715 }
716 void lifo()
717 {
718     if (busy_queue)
719     {
720         struct busy_block* ptemp = busy_queue;
721         while (ptemp && ptemp->next)
722         {
723             ptemp = ptemp->next;
724         }
725         printf("+++++++++++++++++++++被調出的資訊:序號:%d,開始地址:%d,大小:%d, 資料:", \
726             ptemp->id, ptemp->start, ptemp->size);
727         for (int k = 0; k < ptemp->size; ++k)
728         {
729             printf("%c", ptemp->data[k]);
730         }
731         printf("\n");
732         printf("+++++++++++++++++++++排程次數:%d\n", ++ScheduleCnt);
733         struct free_block* pFree = create_free(ptemp->start, ptemp->size, NULL);
734         insert_free(pFree);
735         lifo_delete_busy();
736     }
737     else
738     {
739         printf("無分配塊,無法調出\n");
740     }
741     return;
742 }
743 void FF_rerange()
744 {
745     merge_in();
746     return;
747 }
748 void BF_rerange()
749 {
750     merge_in();
751     free_bubble(2);
752     return;
753 }
754 void WF_rerange()
755 {
756     merge_in();
757     free_bubble(3);
758     return;
759 }
760 void *store_info(void* param)
761 {
762     int choice = *((int*)param);
763     struct free_block* pFree = free_queue;
764     struct busy_block* pBusy = busy_queue;    
765     int subscript = choice == 1 ? numCnt : nameCnt;
766     char *data = choice == 1 ? student_info[subscript].number : student_info[subscript].name;
767     int size = choice == 1 ? 8 : student_info[subscript].name_size;
768     printf("將要放入記憶體的資訊:");
769     for (int c = 0; c < size; ++c)
770     {
771         printf("%c", data[c]);
772     }
773     printf(",大小:%d\n", size);
774     printf("將所有空閒記憶體塊緊縮\n");
775     rerange();
776     show_free();
777     int fEnough = 0;//記憶體大小是否足夠
778     while (!fEnough)
779     {
780         if (pFree && pFree->size >= size)
781         {
782             fEnough = 1;
783             if(choice == 1) ++numCnt;
784             else ++nameCnt;
785             pBusy = create_busy(pFree->start, size, NULL, data);
786             printf("正在儲存的資訊:開始地址:%d, 大小:%d\n", pFree->start, size);
787             delete_free(pFree, size);
788             insert_busy(pBusy);
789             show_busy();
790             break;
791         }
792         else
793         {
794             if (pFree)
795             {
796                 printf("當前指向空閒記憶體大小不夠,跳到下一塊空閒記憶體\n");
797                 pFree = pFree->next;
798             }
799             else
800             {
801                 printf("沒有足夠大小的空閒記憶體可用,開始排程:\n");
802                 schedule();
803                 printf("將所有空閒記憶體塊緊縮並排序\n");
804                 rerange();
805                 show_free();
806                 pFree = free_queue;
807             }
808         }
809     }
810     sleep(1);
811 }
812 void add_task (void *(*task_func)(void *param))
813 {
814     struct task *newtask = (struct task*) malloc (sizeof (struct task));
815     pthread_mutex_lock(&(pool->tcb_lock));
816     newtask->task_func = store_info;//要執行的函式
817     newtask->next = NULL;
818     struct task *pTask = pool->task_queue;
819     if (pTask)
820     {
821         while (pTask && pTask->next)
822             pTask = pTask->next;
823         pTask->next = newtask;
824     }
825     else
826     {
827         pool->task_queue = newtask;
828     }
829     ++pool->task_num;
830     pthread_mutex_unlock(&(pool->tcb_lock));
831     return;
832 }
833 void enqueue(struct tcb_queue  *q, struct TCB* tcb)
834 {
835     q->r = (q->r + 1) % (THREAD_MAXN+1);
836     q->tcbQueue[q->r] = tcb;
837 }
838 struct TCB* dequeue(struct tcb_queue *q)
839 {
840     q->f = (q->f + 1) % (THREAD_MAXN+1);
841     return q->tcbQueue[q->f];
842 }
843 struct TCB* get_front(struct tcb_queue *q)
844 {
845     return q->tcbQueue[(q->f + 1) % (THREAD_MAXN+1)];
846 }
847 bool empty(struct tcb_queue *q)
848 {
849     return q->r == q->f;
850 }
記憶體管理