執行緒池+時間片輪轉法排程+連續記憶體管理+記憶體排程
阿新 • • 發佈:2020-08-11
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 }記憶體管理