├── FIFO.c ├── Makefile ├── PSJF.c ├── README.md ├── RR.c ├── SJF.c ├── calc.c ├── common.c ├── diff.sh ├── diff2.sh ├── heap.c ├── include ├── common.h ├── heap.h ├── merge_sort.h └── priority.h ├── kernel_files ├── pj1_print.c └── pj1_time.c ├── merge_sort.c ├── plot.py ├── process.c ├── report.md ├── scheduler.c └── test ├── FIFO_1.txt ├── FIFO_2.txt ├── FIFO_3.txt ├── FIFO_4.txt ├── FIFO_5.txt ├── PSJF_1.txt ├── PSJF_2.txt ├── PSJF_3.txt ├── PSJF_4.txt ├── PSJF_5.txt ├── RR_1.txt ├── RR_2.txt ├── RR_3.txt ├── RR_4.txt ├── RR_5.txt ├── SJF_1.txt ├── SJF_2.txt ├── SJF_3.txt ├── SJF_4.txt ├── SJF_5.txt └── pj1_test.zip /FIFO.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include "include/common.h" 6 | #include "include/merge_sort.h" 7 | #include "include/priority.h" 8 | 9 | char N[MAX_PROCESS_NUM][MAX_PROCESS_NAME]; 10 | unsigned int R[MAX_PROCESS_NUM], T[MAX_PROCESS_NUM]; 11 | 12 | extern int nProcess; 13 | extern int idxProcess[MAX_PROCESS_NUM]; 14 | extern pid_t pid[MAX_PROCESS_NUM]; 15 | extern int ptrReady; 16 | extern int ptrRun; 17 | extern int run; 18 | 19 | void sig_child(int signum) 20 | { 21 | static int nFinish = 0; 22 | wait(NULL); 23 | ++nFinish; 24 | ++ptrRun; 25 | run = 0; 26 | if (nFinish == nProcess) exit(0); 27 | } 28 | 29 | void increase_next_process_priority() { 30 | int nextRun = idxProcess[ptrRun + 1]; 31 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_INIT); 32 | } 33 | 34 | void run_next_process() { 35 | int nextRun = idxProcess[ptrRun]; 36 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_HIGH); 37 | run = 1; 38 | } 39 | 40 | void change_priority() { 41 | if (!run && ptrRun < ptrReady) 42 | run_next_process(); 43 | if (run && ptrRun + 1 < ptrReady) 44 | increase_next_process_priority(); 45 | } 46 | 47 | int main (void) 48 | { 49 | READ_INPUT(); 50 | 51 | for (int i = 0; i < nProcess; ++i) 52 | idxProcess[i] = i; 53 | sort(nProcess, idxProcess, R); 54 | 55 | SIGACT_SIGCHLD(); 56 | 57 | int nextReady = idxProcess[ptrReady]; 58 | 59 | for (int t = 0, i = nProcess; i > 0; ++t) { 60 | change_priority(); 61 | while (ptrReady < nProcess && t == R[nextReady]) { 62 | create_process(&pid[nextReady], N[nextReady], nextReady, T[nextReady]); 63 | nextReady = idxProcess[++ptrReady]; 64 | change_priority(); 65 | } 66 | unit_time(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # all: calc 3 | all: process scheduler calc 4 | 5 | process: 6 | gcc -O2 process.c common.c -o process 7 | 8 | scheduler: 9 | gcc -O2 FIFO.c common.c merge_sort.c -o FIFO 10 | gcc -O2 RR.c common.c merge_sort.c -o RR 11 | gcc -O2 SJF.c common.c merge_sort.c heap.c -o SJF 12 | gcc -O2 PSJF.c common.c merge_sort.c heap.c -o PSJF 13 | gcc -O2 scheduler.c common.c -o scheduler 14 | 15 | calc: 16 | gcc -O2 calc.c common.c merge_sort.c heap.c -o calc 17 | 18 | clean: 19 | @rm process scheduler FIFO SJF RR PSJF calc 20 | -------------------------------------------------------------------------------- /PSJF.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include "include/common.h" 6 | #include "include/merge_sort.h" 7 | #include "include/priority.h" 8 | #include "include/heap.h" 9 | 10 | char N[MAX_PROCESS_NUM][MAX_PROCESS_NAME]; 11 | unsigned int R[MAX_PROCESS_NUM], T[MAX_PROCESS_NUM]; 12 | 13 | extern int nProcess; 14 | extern int idxProcess[MAX_PROCESS_NUM]; 15 | extern pid_t pid[MAX_PROCESS_NUM]; 16 | extern int ptrReady; 17 | extern int run; 18 | 19 | int nFinish = 0; 20 | int now_time = 0; 21 | int counting_time = 0; 22 | struct Node *heap_root = NULL; 23 | 24 | #define BLOCK_SIGCHLD() \ 25 | sigset_t set, oset; \ 26 | do { \ 27 | sigfillset(&set); \ 28 | sigprocmask(SIG_BLOCK, &set, &oset); \ 29 | } while(0) 30 | 31 | #define UNBLOCK_SIGCHLD() sigprocmask(SIG_SETMASK, &oset, NULL) 32 | 33 | #define WAIT_CHILD() do { \ 34 | BLOCK_SIGCHLD(); \ 35 | while (heap_root != NULL && waitpid(pid[heap_root->index], NULL, WNOHANG) != 0) { \ 36 | ++nFinish; \ 37 | heap_root = pop_heap(heap_root); \ 38 | run = 0; \ 39 | if (nFinish == nProcess) exit(0); \ 40 | } \ 41 | UNBLOCK_SIGCHLD(); \ 42 | } while(0) 43 | 44 | void sig_child(int signum) 45 | { 46 | wait(NULL); 47 | ++nFinish; 48 | heap_root = pop_heap(heap_root); 49 | run = 0; 50 | if (nFinish == nProcess) exit(0); 51 | } 52 | 53 | void increase_next_process_priority() { 54 | BLOCK_SIGCHLD(); 55 | int i1 = heap_root->index; 56 | heap_root = pop_heap(heap_root); 57 | SET_PRIORITY(pid[i1], SCHED_FIFO, PRIORITY_HIGH); 58 | WAIT_CHILD(); 59 | if (heap_root) { 60 | int i2 = heap_root->index; 61 | SET_PRIORITY(pid[i2], SCHED_FIFO, PRIORITY_INIT); 62 | } 63 | heap_root = insert_heap(heap_root, T[i1], i1); 64 | UNBLOCK_SIGCHLD(); 65 | } 66 | 67 | void decrease_next_two_processes_priority() { 68 | BLOCK_SIGCHLD(); 69 | if (!run || heap_root == NULL) 70 | return; 71 | int i1 = heap_root->index; 72 | heap_root = pop_heap(heap_root); 73 | T[i1] -= counting_time; 74 | WAIT_CHILD(); 75 | if (heap_root) { 76 | int i2 = heap_root->index; 77 | SET_PRIORITY(pid[i2], SCHED_FIFO, PRIORITY_LOW); 78 | } 79 | SET_PRIORITY(pid[i1], SCHED_FIFO, PRIORITY_LOW); 80 | heap_root = insert_heap(heap_root, T[i1], i1); 81 | counting_time = 0; 82 | UNBLOCK_SIGCHLD(); 83 | } 84 | 85 | void run_next_process() { 86 | BLOCK_SIGCHLD(); 87 | int nextRun = heap_root->index; 88 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_HIGH); 89 | run = 1; 90 | counting_time = 0; 91 | UNBLOCK_SIGCHLD(); 92 | } 93 | 94 | void change_priority() { 95 | WAIT_CHILD(); 96 | BLOCK_SIGCHLD(); 97 | if (!run && heap_root != NULL) 98 | run_next_process(); 99 | if (run && heap_root != NULL) 100 | increase_next_process_priority(); 101 | UNBLOCK_SIGCHLD(); 102 | } 103 | 104 | int main (void) 105 | { 106 | READ_INPUT(); 107 | 108 | for (int i = 0; i < nProcess; ++i) 109 | idxProcess[i] = i; 110 | sort(nProcess, idxProcess, T); 111 | sort(nProcess, idxProcess, R); 112 | 113 | SIGACT_SIGCHLD(); 114 | 115 | int nextReady = idxProcess[ptrReady]; 116 | 117 | for (int t = 0; ; ++t) { 118 | change_priority(); 119 | while (ptrReady < nProcess && t == R[nextReady]) { 120 | decrease_next_two_processes_priority(); 121 | create_process(&pid[nextReady], N[nextReady], nextReady, T[nextReady]); 122 | heap_root = insert_heap(heap_root, T[nextReady], nextReady); 123 | nextReady = idxProcess[++ptrReady]; 124 | change_priority(); 125 | } 126 | unit_time(); 127 | counting_time++; 128 | now_time++; 129 | WAIT_CHILD(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2019 Spring - Operating System Project 1 @ NTU 2 | 3 | ## Member 4 | 5 | * 資工二 b06902093 王彥仁 6 | * 資工二 b06902026 吳秉柔 7 | * 資工二 b06902041 吳采耘 8 | * 資工二 b06902054 蔡宥杏 9 | * 醫學三 b05401009 謝德威 10 | * 電機五 b03901056 孫凡耕 11 | 12 | ## Usage 13 | 14 | ```sh 15 | make 16 | sudo ./scheduler < test_data 17 | ``` 18 | 19 | ## Report 20 | [Report](https://github.com/wangyenjen/OS-Project-1/blob/master/report.md) 21 | -------------------------------------------------------------------------------- /RR.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include "include/common.h" 6 | #include "include/merge_sort.h" 7 | #include "include/priority.h" 8 | 9 | #define MAX_QUEUE_SIZE (1000000 + 7) 10 | #define TIME_QUANTUM 500 11 | 12 | char N[MAX_PROCESS_NUM][MAX_PROCESS_NAME]; 13 | unsigned int R[MAX_PROCESS_NUM], T[MAX_PROCESS_NUM]; 14 | 15 | extern int nProcess; 16 | extern int idxProcess[MAX_PROCESS_NUM]; 17 | extern pid_t pid[MAX_PROCESS_NUM]; 18 | extern int ptrReady; 19 | extern int run; 20 | 21 | int counting_time = 0, block_flag = 0; 22 | int que[MAX_QUEUE_SIZE], ptrFront = 0, ptrBack = 0; 23 | 24 | void push_queue(int x) { 25 | que[ptrBack++] = x; 26 | } 27 | 28 | int front_queue() { 29 | return que[ptrFront]; 30 | } 31 | 32 | int size_queue() { 33 | return ptrBack - ptrFront; 34 | } 35 | 36 | int empty_queue() { 37 | return ptrFront < ptrBack ? 0 : 1; 38 | } 39 | 40 | void pop_queue() { 41 | if (ptrFront < ptrBack) 42 | ptrFront++; 43 | } 44 | 45 | void sig_child(int signum) 46 | { 47 | static int nFinish = 0; 48 | wait(NULL); 49 | ++nFinish; 50 | pop_queue(); 51 | run = 0; 52 | block_flag = 0; 53 | counting_time = 0; 54 | if (nFinish == nProcess) exit(0); 55 | } 56 | 57 | void increase_next_process_priority() { 58 | int nextRun = que[ptrFront + 1]; 59 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_INIT); 60 | } 61 | 62 | void run_next_process() { 63 | counting_time = 0; 64 | int nextRun = que[ptrFront]; 65 | if (T[nextRun] <= TIME_QUANTUM) 66 | block_flag = 1; 67 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_HIGH); 68 | run = 1; 69 | } 70 | 71 | void change_priority() { 72 | if (!run && size_queue() >= 1) 73 | run_next_process(); 74 | if (run && size_queue() >= 2) 75 | increase_next_process_priority(); 76 | } 77 | 78 | int main (void) 79 | { 80 | READ_INPUT(); 81 | 82 | for (int i = 0; i < nProcess; ++i) 83 | idxProcess[i] = i; 84 | sort(nProcess, idxProcess, R); 85 | 86 | SIGACT_SIGCHLD(); 87 | 88 | int nextReady = idxProcess[ptrReady]; 89 | 90 | for (int t = 0, i = nProcess; i > 0; ++t) { 91 | change_priority(); 92 | while (ptrReady < nProcess && t == R[nextReady]) { 93 | create_process(&pid[nextReady], N[nextReady], nextReady, T[nextReady]); 94 | push_queue(nextReady); 95 | nextReady = idxProcess[++ptrReady]; 96 | change_priority(); 97 | } 98 | unit_time(); 99 | counting_time++; 100 | if (!block_flag && run && counting_time == TIME_QUANTUM) { 101 | int id = front_queue(); 102 | pop_queue(); 103 | T[id] -= TIME_QUANTUM; 104 | SET_PRIORITY(pid[id], SCHED_FIFO, PRIORITY_LOW); 105 | push_queue(id); 106 | run = 0; 107 | change_priority(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /SJF.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include "include/common.h" 6 | #include "include/merge_sort.h" 7 | #include "include/priority.h" 8 | #include "include/heap.h" 9 | 10 | char N[MAX_PROCESS_NUM][MAX_PROCESS_NAME]; 11 | unsigned int R[MAX_PROCESS_NUM], T[MAX_PROCESS_NUM]; 12 | 13 | extern int nProcess; 14 | extern int idxProcess[MAX_PROCESS_NUM]; 15 | extern pid_t pid[MAX_PROCESS_NUM]; 16 | extern int ptrReady; 17 | extern int ptrRun; 18 | extern int run; 19 | 20 | struct Node *heap_root = NULL; 21 | 22 | void sig_child(int signum) 23 | { 24 | static int nFinish = 0; 25 | wait(NULL); 26 | ++nFinish; 27 | ++ptrRun; 28 | run = 0; 29 | if (nFinish == nProcess) exit(0); 30 | } 31 | 32 | void increase_next_process_priority() { 33 | int nextRun = heap_root->index; 34 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_INIT); 35 | } 36 | 37 | void decrease_next_process_priority() { 38 | if (!run || heap_root == NULL) 39 | return; 40 | int nextRun = heap_root->index; 41 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_LOW); 42 | } 43 | 44 | void run_next_process() { 45 | int nextRun = heap_root->index; 46 | heap_root = pop_heap(heap_root); 47 | SET_PRIORITY(pid[nextRun], SCHED_FIFO, PRIORITY_HIGH); 48 | run = 1; 49 | } 50 | 51 | void change_priority() { 52 | if (!run && heap_root != NULL) 53 | run_next_process(); 54 | if (run && heap_root != NULL) 55 | increase_next_process_priority(); 56 | } 57 | 58 | int main (void) 59 | { 60 | READ_INPUT(); 61 | 62 | for (int i = 0; i < nProcess; ++i) 63 | idxProcess[i] = i; 64 | sort(nProcess, idxProcess, T); 65 | sort(nProcess, idxProcess, R); 66 | 67 | SIGACT_SIGCHLD(); 68 | 69 | int nextReady = idxProcess[ptrReady]; 70 | 71 | for (int t = 0, i = nProcess; i > 0; ++t) { 72 | change_priority(); 73 | while (ptrReady < nProcess && t == R[nextReady]) { 74 | decrease_next_process_priority(); 75 | create_process(&pid[nextReady], N[nextReady], nextReady, T[nextReady]); 76 | heap_root = insert_heap(heap_root, T[nextReady], nextReady); 77 | nextReady = idxProcess[++ptrReady]; 78 | change_priority(); 79 | } 80 | unit_time(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /calc.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "include/merge_sort.h" 8 | #include "include/common.h" 9 | #include "include/heap.h" 10 | 11 | extern int nProcess; 12 | extern int idxProcess[MAX_PROCESS_NUM]; 13 | 14 | char N[MAX_PROCESS_NUM][MAX_PROCESS_NAME]; 15 | unsigned int R[MAX_PROCESS_NUM], T[MAX_PROCESS_NUM]; 16 | int first_time = -1, last_time = 0; 17 | unsigned int start_time[MAX_PROCESS_NUM], finish_time[MAX_PROCESS_NUM]; 18 | 19 | void calc_FIFO() { 20 | sort(nProcess, idxProcess, R); 21 | for (int i = 0; i < nProcess; ++i) { 22 | int nxt = idxProcess[i]; 23 | start_time[nxt] = (last_time > R[nxt] ? last_time : R[nxt]); 24 | if (first_time == -1) 25 | first_time = start_time[nxt]; 26 | last_time = finish_time[nxt] = start_time[nxt] + T[nxt]; 27 | fprintf(stderr, "%s %u %u\n", N[nxt], start_time[nxt], finish_time[nxt]); 28 | } 29 | } 30 | void calc_SJF() { 31 | sort(nProcess, idxProcess, T); 32 | sort(nProcess, idxProcess, R); 33 | 34 | struct Node *heap_root = NULL; 35 | 36 | int *p = idxProcess; 37 | 38 | while (heap_root != NULL || p - idxProcess < nProcess) { 39 | if (heap_root == NULL && R[*p] > last_time) 40 | last_time = R[*p]; 41 | while(p - idxProcess < nProcess && R[*p] <= last_time) { 42 | heap_root = insert_heap(heap_root, T[*p], *p); 43 | ++p; 44 | } 45 | int nxt = heap_root->index; 46 | heap_root = pop_heap(heap_root); 47 | start_time[nxt] = last_time; 48 | if (first_time == -1) 49 | first_time = start_time[nxt]; 50 | last_time = finish_time[nxt] = last_time + T[nxt]; 51 | fprintf(stderr, "%s %u %u\n", N[nxt], start_time[nxt], finish_time[nxt]); 52 | } 53 | } 54 | 55 | void calc_RR() { 56 | static const int MAX_QUEUE_SIZE = 1000000 + 7; 57 | static const int TIME_QUANTUM = 500; 58 | 59 | int que[MAX_QUEUE_SIZE], time_left[MAX_PROCESS_NUM]; 60 | int ptrFront = 0, ptrBack = 0; 61 | 62 | memcpy(time_left, T, sizeof(int) * nProcess); 63 | memset(start_time, -1, sizeof(int) * nProcess); 64 | sort(nProcess, idxProcess, R); 65 | 66 | int nFinish = 0, *p = idxProcess, nxt = -1; 67 | while (nFinish < nProcess) { 68 | if (ptrBack == ptrFront && nxt == -1 && R[*p] > last_time) 69 | last_time = R[*p]; 70 | 71 | while(p - idxProcess < nProcess && R[*p] <= last_time) { 72 | que[ptrBack++] = *p; 73 | ++p; 74 | } 75 | if (nxt != -1) 76 | que[ptrBack++] = nxt; 77 | 78 | nxt = que[ptrFront++]; 79 | if (start_time[nxt] == -1) { 80 | start_time[nxt] = last_time; 81 | if (first_time == -1) 82 | first_time = start_time[nxt]; 83 | } 84 | int exec_time = 85 | TIME_QUANTUM < time_left[nxt] ? TIME_QUANTUM : time_left[nxt]; 86 | last_time += exec_time; 87 | time_left[nxt] -= exec_time; 88 | if (time_left[nxt] == 0) { 89 | finish_time[nxt] = last_time; 90 | ++nFinish; 91 | fprintf(stderr, "%s %u %u\n", N[nxt], start_time[nxt], finish_time[nxt]); 92 | nxt = -1; 93 | } 94 | } 95 | } 96 | 97 | 98 | void calc_PSJF() { 99 | sort(nProcess, idxProcess, T); 100 | sort(nProcess, idxProcess, R); 101 | 102 | struct Node *heap_root = NULL; 103 | 104 | int time_left[MAX_PROCESS_NUM]; 105 | memcpy(time_left, T, sizeof(int) * nProcess); 106 | memset(start_time, -1, sizeof(int) * nProcess); 107 | 108 | int *p = idxProcess; 109 | while (heap_root != NULL || p - idxProcess < nProcess) { 110 | if (heap_root == NULL && R[*p] > last_time) 111 | last_time = R[*p]; 112 | while (p - idxProcess < nProcess && R[*p] == last_time) { 113 | heap_root = insert_heap(heap_root, time_left[*p], *p); 114 | ++p; 115 | } 116 | int nxt = heap_root->index; 117 | heap_root = pop_heap(heap_root); 118 | if (start_time[nxt] == -1) { 119 | start_time[nxt] = last_time; 120 | if (first_time == -1) 121 | first_time = start_time[nxt]; 122 | } 123 | if (p - idxProcess < nProcess && last_time + time_left[nxt] > R[*p]) { 124 | int exec_time = R[*p] - last_time; 125 | time_left[nxt] -= exec_time; 126 | last_time += exec_time; 127 | heap_root = insert_heap(heap_root, time_left[nxt], nxt); 128 | } else { 129 | last_time = finish_time[nxt] = last_time + time_left[nxt]; 130 | time_left[nxt] = 0; 131 | fprintf(stderr, "%s %u %u\n", N[nxt], start_time[nxt], finish_time[nxt]); 132 | } 133 | } 134 | } 135 | 136 | int main(int argc, char **argv) { 137 | 138 | char scheduling_policy[MAX_SCHEDULE_NAME]; 139 | 140 | assert(scanf("%s", scheduling_policy) == 1); 141 | 142 | const char scheduling_types[NUM_SCHEDULING_TYPE][MAX_SCHEDULE_NAME] 143 | = { "FIFO", "RR", "SJF", "PSJF" }; 144 | for (int i = 0; i <= NUM_SCHEDULING_TYPE; ++i) { 145 | if (i == NUM_SCHEDULING_TYPE) { 146 | fprintf(stderr, "no such scheduling type\n"); 147 | return 1; 148 | } 149 | if (strcmp(scheduling_policy, scheduling_types[i]) == 0) break; 150 | } 151 | 152 | READ_INPUT(); 153 | for (int i = 0; i < nProcess; ++i) 154 | idxProcess[i] = i; 155 | 156 | switch(scheduling_policy[0]) { 157 | case 'F': 158 | calc_FIFO(); 159 | break; 160 | case 'R': 161 | calc_RR(); 162 | // fprintf(stderr, "-----------\n"); 163 | // calc_easy_RR(); 164 | break; 165 | case 'S': 166 | calc_SJF(); 167 | break; 168 | case 'P': 169 | calc_PSJF(); 170 | break; 171 | } 172 | fprintf(stderr, "first time = %d\n", first_time); 173 | fprintf(stderr, "last time = %d\n", last_time); 174 | 175 | double exec_first_time = 1e100, exec_last_time = 0; 176 | double exec_start_time[MAX_PROCESS_NUM], exec_finish_time[MAX_PROCESS_NUM]; 177 | char message[1000]; 178 | FILE *pFile = fopen(argv[1], "r"); 179 | while(fgets(message, 1000, pFile) != NULL) { 180 | // fprintf(stderr, "message = %s\n", message); 181 | if (strncmp(message, "[Project1]", 10) == 0) { 182 | strtok(message, " "); 183 | int idx = atoi(strtok(NULL, " ")); 184 | // fprintf(stderr, "idx = %d\n", idx); 185 | exec_start_time[idx] = atof(strtok(NULL, " ")); 186 | if (exec_start_time[idx] < exec_first_time) 187 | exec_first_time = exec_start_time[idx]; 188 | exec_finish_time[idx] = atof(strtok(NULL, " ")); 189 | exec_last_time = exec_finish_time[idx]; 190 | } 191 | } 192 | fclose(pFile); 193 | 194 | fprintf(stderr, "exec first time = %.8f\n", exec_first_time); 195 | fprintf(stderr, "exec last time = %.8f\n", exec_last_time); 196 | 197 | double avg_unit_time 198 | = (exec_last_time - exec_first_time) / (last_time - first_time); 199 | fprintf(stderr, "avg unit time = %0.8f\n", avg_unit_time); 200 | double total_error = 0; 201 | for (int i = 0; i < nProcess; ++i) { 202 | double start_time_error = 203 | (start_time[i] - first_time) * avg_unit_time - 204 | (exec_start_time[i] - exec_first_time); 205 | double finish_time_error = 206 | (finish_time[i] - first_time) * avg_unit_time - 207 | (exec_finish_time[i] - exec_first_time); 208 | fprintf(stderr, "error of %s: start time: %1.8f, finish time: %1.8f\n", 209 | N[i], start_time_error, finish_time_error); 210 | total_error += 211 | (start_time_error < 0 ? -start_time_error : start_time_error); 212 | total_error += 213 | (finish_time_error < 0 ? -finish_time_error : finish_time_error); 214 | } 215 | fprintf(stderr, "total error = %1.8f\n", total_error); 216 | // for (int i = 0; i < nProcess; ++i) { 217 | // int j = idxProcess[i]; 218 | // fprintf(stderr, "%s %u %u\n", N[j], start_time[j], finish_time[j]); 219 | // } 220 | } 221 | 222 | // int calc_easy_RR() { 223 | // static const int MAX_QUEUE_SIZE = 1000000 + 7; 224 | // static const int TIME_QUANTUM = 500; 225 | // 226 | // int que[MAX_QUEUE_SIZE], time_left[MAX_PROCESS_NUM]; 227 | // int ptrFront = 0, ptrBack = 0; 228 | // 229 | // memcpy(time_left, T, sizeof(int) * nProcess); 230 | // memset(start_time, -1, sizeof(int) * nProcess); 231 | // 232 | // int last_time = 0, nFinish = 0, *p = idxProcess, nxt = -1; 233 | // while(nFinish < nProcess) { 234 | // 235 | // while(p - idxProcess < nProcess && R[*p] == last_time) { 236 | // que[ptrBack++] = *p; 237 | // ++p; 238 | // } 239 | // if (ptrFront < ptrBack) { 240 | // int nxt = que[ptrFront++]; 241 | // if (start_time[nxt] == -1) 242 | // start_time[nxt] = last_time; 243 | // int exec_time = 244 | // TIME_QUANTUM < time_left[nxt] ? TIME_QUANTUM : time_left[nxt]; 245 | // while(exec_time--) { 246 | // --time_left[nxt]; 247 | // ++last_time; 248 | // while(p - idxProcess < nProcess && R[*p] == last_time) { 249 | // que[ptrBack++] = *p; 250 | // ++p; 251 | // } 252 | // } 253 | // while(p - idxProcess < nProcess && R[*p] == last_time) { 254 | // que[ptrBack++] = *p; 255 | // ++p; 256 | // } 257 | // if (time_left[nxt] == 0) { 258 | // finish_time[nxt] = last_time; 259 | // ++nFinish; 260 | // fprintf(stderr, "%s %u %u\n", N[nxt], start_time[nxt], finish_time[nxt]); 261 | // } else { 262 | // que[ptrBack++] = nxt; 263 | // } 264 | // } else 265 | // ++last_time; 266 | // } 267 | // } 268 | -------------------------------------------------------------------------------- /common.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "include/common.h" 10 | #include "include/priority.h" 11 | 12 | int nProcess; 13 | int idxProcess[MAX_PROCESS_NUM]; 14 | pid_t pid[MAX_PROCESS_NUM]; 15 | int ptrReady = 0; 16 | int ptrRun = 0; 17 | int run = 0; 18 | 19 | void unit_time() { 20 | volatile unsigned long i; 21 | for (i = 0; i < TIME_UNIT; i++); 22 | } 23 | 24 | void create_process (pid_t *pid, char *N, int I, int T) 25 | { 26 | if ((*pid = fork()) < 0) ERR_EXIT("fork() error"); 27 | if (*pid == 0) { 28 | char execute_time[20], idx[10]; 29 | sprintf(execute_time, "%u", T); 30 | sprintf(idx, "%u", I); 31 | execl("./process", "./process", N, idx, execute_time, (char *)0); 32 | } 33 | if (*pid > 0) { 34 | fflush(stderr); 35 | SET_PRIORITY(*pid, SCHED_FIFO, PRIORITY_LOW); 36 | USE_CPU(*pid, 1); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /diff.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo ./scheduler < $1 2> output.txt 4 | 5 | ./calc output.txt < $1 6 | 7 | rm output.txt 8 | -------------------------------------------------------------------------------- /diff2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # sudo ./scheduler < $1 > output2.txt 4 | # ./calc output2.txt < $1 5 | for t in RR SJF PSJF FIFO ; do 6 | for i in {1..5} ; do 7 | echo "----------------------"$t"_$i----------------------------" 8 | sudo ./scheduler < "test/"$t"_$i.txt" 2> "outputs/schd_"$t"_$i.txt" 9 | ./calc "outputs/schd_"$t"_$i.txt" < "test/"$t"_$i.txt" &> "outputs/calc_"$t"_$i.txt" 10 | done 11 | done 12 | -------------------------------------------------------------------------------- /heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Node { 5 | struct Node *lc, *rc; 6 | int dist, value, size, index; 7 | }; 8 | 9 | struct Node* new_Node(int value, int index) { 10 | struct Node *o = (struct Node*)malloc(sizeof(struct Node)); 11 | o->lc = 0; 12 | o->rc = 0; 13 | o->dist = 0; 14 | o->value = value; 15 | o->size = 1; 16 | o->index = index; 17 | return o; 18 | } 19 | 20 | #define swap_Node(a, b) do { \ 21 | struct Node *c = (b); \ 22 | (b) = (a); \ 23 | (a) = (c); \ 24 | } while (0) 25 | 26 | int get_size(struct Node *o) { 27 | return o ? o->size : 0; 28 | } 29 | 30 | void maintain(struct Node *o) { 31 | o->size = get_size(o->lc) + 1 + get_size(o->rc); 32 | } 33 | 34 | struct Node* merge(struct Node *a, struct Node *b) { 35 | if (a == NULL || b == NULL) 36 | return (a == NULL ? b : a); 37 | 38 | if (b->value < a->value) 39 | swap_Node(a, b); 40 | 41 | a->size += b->size; 42 | a->rc = merge(a->rc, b); 43 | 44 | if (a->lc == NULL && a->rc) 45 | swap_Node(a->lc, a->rc); 46 | else if (a->rc && a->lc->dist < a->rc->dist) 47 | swap_Node(a->lc, a->rc); 48 | 49 | if (a->rc == 0) 50 | a->dist = 0; 51 | else 52 | a->dist = a->rc->dist + 1; 53 | 54 | maintain(a); 55 | 56 | return a; 57 | } 58 | 59 | struct Node* insert_heap(struct Node* root, int value, int index) { 60 | root = merge(root, new_Node(value, index)); 61 | return root; 62 | } 63 | 64 | struct Node* pop_heap(struct Node *root) { 65 | struct Node *tmp = root; 66 | root = merge(root->lc, root->rc); 67 | free(tmp); 68 | return root; 69 | } 70 | 71 | int test() { 72 | struct Node *root = NULL; 73 | root = merge(root, new_Node(87, 1)); 74 | root = merge(root, new_Node(55, 2)); 75 | root = merge(root, new_Node(96, 3)); 76 | while (root) { 77 | printf("index = %d, size = %d: %d\n", root->index, root->size, root->value); 78 | root = merge(root->lc, root->rc); 79 | } 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX_PROCESS_NUM 10000 4 | #define MAX_NAME_LENGTH 16 5 | #define MAX_SCHEDULE_NAME 10 6 | #define MAX_PROCESS_NAME 40 7 | #define NUM_SCHEDULING_TYPE 4 8 | #define TIME_UNIT 1000000UL 9 | 10 | #define ERR_EXIT(a) do { \ 11 | perror(a); exit(1); \ 12 | } while (0) 13 | 14 | #define READ_INPUT() do { \ 15 | assert(scanf("%d", &nProcess) == 1); \ 16 | for (int i = 0; i < nProcess; ++i) { \ 17 | assert(scanf("%s%u%u", N[i], &R[i], &T[i]) == 3); \ 18 | } \ 19 | } while(0) 20 | 21 | #define SIGACT_SIGCHLD() do { \ 22 | struct sigaction act; \ 23 | act.sa_flags = 0; \ 24 | act.sa_handler = sig_child; \ 25 | sigfillset(&act.sa_mask); \ 26 | sigaction(SIGCHLD, &act, NULL); \ 27 | } while(0) 28 | 29 | void unit_time(); 30 | 31 | void create_process (pid_t *pid, char *N, int id, int T); 32 | -------------------------------------------------------------------------------- /include/heap.h: -------------------------------------------------------------------------------- 1 | struct Node { 2 | struct Node *lc, *rc; 3 | int dist, value, size, index; 4 | }; 5 | 6 | int get_size(struct Node *o); 7 | 8 | struct Node* insert_heap(struct Node* root, int value, int index); 9 | 10 | struct Node* pop_heap(); 11 | -------------------------------------------------------------------------------- /include/merge_sort.h: -------------------------------------------------------------------------------- 1 | void sort(int n, int idx[], unsigned int R[]); 2 | -------------------------------------------------------------------------------- /include/priority.h: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // priority value: [1, 99] 9 | #define PRIORITY_INIT (int)50 10 | #define PRIORITY_LOW (int)10 11 | #define PRIORITY_HIGH (int)80 12 | 13 | #define PRINT_ERROR(name) do { \ 14 | fprintf(stderr, "[Error] %s: %d - ", __PRETTY_FUNCTION__, __LINE__); \ 15 | perror(name); \ 16 | exit(EXIT_FAILURE); \ 17 | } while (0) 18 | 19 | #define USE_CPU(pid, x) do { \ 20 | cpu_set_t mask; \ 21 | CPU_ZERO(&mask); \ 22 | CPU_SET((x), &mask); \ 23 | if (sched_setaffinity((pid), sizeof(mask), &mask) != 0) { \ 24 | PRINT_ERROR("sched_setaffinity"); \ 25 | } \ 26 | } while (0) 27 | 28 | #define SET_PRIORITY(pid, policy, priority) do { \ 29 | /* policy: SCHED_FIFO, SCHED_RR, SCHED_BATCH */ \ 30 | /* real time scheduler policy (require root permission): SCHED_FIFO, SCHED_RR */ \ 31 | /* non-real time scheduler policy: SCHED_BATCH */ \ 32 | struct sched_param param; \ 33 | param.sched_priority = priority; \ 34 | if (sched_setscheduler(pid, policy, ¶m) != 0) { \ 35 | PRINT_ERROR("sched_setscheduler"); \ 36 | } \ 37 | } while (0) 38 | 39 | /* 40 | static int test() { 41 | USE_CPU(getpid(), 1); 42 | SET_PRIORITY(getpid(), SCHED_FIFO, PRIORITY_INIT); 43 | while (1) { 44 | volatile unsigned long i; 45 | for(i = 0; i < 1000000UL; i++); 46 | } 47 | return 0; 48 | } 49 | */ 50 | -------------------------------------------------------------------------------- /kernel_files/pj1_print.c: -------------------------------------------------------------------------------- 1 | // syscall #351 2 | 3 | #include 4 | #include 5 | 6 | asmlinkage void sys_pj1_print(int pid, long start_time, long end_time) { 7 | static const long BASE = 1000000000; 8 | printk(KERN_INFO "[Project1] %d %ld.%09ld %ld.%09ld", pid, start_time / BASE, start_time % BASE, end_time / BASE, end_time % BASE); 9 | } 10 | -------------------------------------------------------------------------------- /kernel_files/pj1_time.c: -------------------------------------------------------------------------------- 1 | // syscall #352 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | asmlinkage long sys_pj1_time(void) { 8 | static const long BASE = 1000000000; 9 | struct timespec t; 10 | getnstimeofday(&t); 11 | return t.tv_sec * BASE + t.tv_nsec; 12 | } 13 | -------------------------------------------------------------------------------- /merge_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX_ARRAY_LENGTH (100000 + 7) 4 | 5 | int tmp_array_for_sort[MAX_ARRAY_LENGTH]; 6 | void _sort(int lb, int rb, int idx[], unsigned int R[]) { // [lb, rb] 7 | if (lb >= rb) 8 | return; 9 | 10 | int mid = (lb + rb) >> 1; 11 | 12 | _sort(lb, mid, idx, R); 13 | _sort(mid + 1, rb, idx, R); 14 | 15 | int i1 = lb, i2 = mid + 1, p = lb; 16 | while (i1 <= mid || i2 <= rb) { 17 | if (i1 <= mid && i2 <= rb) { 18 | if (R[idx[i1]] <= R[idx[i2]]) 19 | tmp_array_for_sort[p++] = idx[i1++]; 20 | else 21 | tmp_array_for_sort[p++] = idx[i2++]; 22 | } 23 | else if (i1 <= mid) 24 | tmp_array_for_sort[p++] = idx[i1++]; 25 | else 26 | tmp_array_for_sort[p++] = idx[i2++]; 27 | } 28 | 29 | int i; 30 | for (i = lb; i <= rb; i++) 31 | idx[i] = tmp_array_for_sort[i]; 32 | } 33 | 34 | void sort(int n, int idx[], unsigned int R[]) { 35 | // idx: 0, 1, 2, ..., n; 36 | // sort idx according to R[idx]; 37 | _sort(0, n - 1, idx, R); 38 | } 39 | 40 | int idx[MAX_ARRAY_LENGTH]; 41 | unsigned int R[MAX_ARRAY_LENGTH]; 42 | 43 | static int test() { 44 | int n = 5; 45 | for (int i = 0; i < n; i++) { 46 | idx[i] = i; 47 | } 48 | R[0] = 100, R[1] = 50, R[2] = 150, R[3] = 87, R[4] = 26; 49 | sort(n, idx, R); 50 | for (int i = 0; i < n; i++) 51 | printf("%d: %d\n", idx[i], R[idx[i]]); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | from matplotlib import cm 3 | import numpy as np 4 | 5 | SCHD_TYPES = ['FIFO', 'RR', 'SJF', 'PSJF'] 6 | TOTAL_COUNT = 5 7 | W_FACTOR = 10 8 | H_FACTOR = 10 9 | H_OFFSET = 10 10 | H_DIST = 20 11 | GREENS = cm.get_cmap('Greens', 8) 12 | REDS = cm.get_cmap('Reds', 8) 13 | 14 | for schd in SCHD_TYPES: 15 | for n in range(1, TOTAL_COUNT+1): 16 | 17 | fig, ax = plt.subplots() 18 | 19 | test_file = 'test/' + schd + '_' + str(n) + '.txt' 20 | schd_file = 'outputs/schd_' + schd + '_' + str(n) + '.txt' 21 | calc_file = 'outputs/calc_' + schd + '_' + str(n) + '.txt' 22 | 23 | y_ticklabels = [] 24 | name_dict, indx_dict = dict(), dict() 25 | test_lines = open(test_file, 'r').read().splitlines() 26 | for i in range(2, len(test_lines)): 27 | name = test_lines[i].split()[0] 28 | y_ticklabels.append(name) 29 | name_dict[name] = i-2 30 | indx_dict[i-2] = name 31 | 32 | num = len(y_ticklabels) 33 | 34 | schd_times = list(range(num)) 35 | schd_lines = open(schd_file, 'r').read().splitlines() 36 | for l in schd_lines: 37 | if l[:10] == '[Project1]': 38 | _, indx, st, ed = l.split() 39 | st = float(st) 40 | ed = float(ed) 41 | # name = indx_dict[indx] 42 | schd_times[int(indx)] = (st, ed) 43 | 44 | calc_times = list(range(num)) 45 | calc_lines = open(calc_file, 'r').read().splitlines() 46 | for l in calc_lines: 47 | if l[:9] == 'error of ': 48 | _, _, name, _, _, err_st, _, _, err_ed = l.split() 49 | err_st = float(err_st[:-1]) 50 | err_ed = float(err_ed) 51 | indx = name_dict[name[:-1]] 52 | calc_times[indx] = (schd_times[indx][0] + err_st, 53 | schd_times[indx][1] + err_ed) 54 | elif l[:14] == 'total error = ': 55 | total_err = float(l.split()[-1]) 56 | 57 | min_time, max_time = 1e100, 0 58 | 59 | for i in range(num): 60 | min_time = min(min_time, schd_times[i][0], calc_times[i][0]) 61 | max_time = max(max_time, schd_times[i][0], calc_times[i][0]) 62 | 63 | for i in range(num): 64 | schd_times[i] = (schd_times[i][0] - min_time, schd_times[i][1] - min_time) 65 | calc_times[i] = (calc_times[i][0] - min_time, calc_times[i][1] - min_time) 66 | # schd_times[i] = (schd_times[i][0] * W_FACTOR / max_time, 67 | # schd_times[i][1] * W_FACTOR / max_time) 68 | # calc_times[i] = (calc_times[i][0] * W_FACTOR / max_time, 69 | # calc_times[i][1] * W_FACTOR / max_time) 70 | 71 | x_ticks, y_ticks = [], [] 72 | for i in range(num): 73 | ax.broken_barh([(schd_times[i][0], schd_times[i][1] - schd_times[i][0])], 74 | (H_OFFSET + 2*i*H_FACTOR, H_FACTOR), facecolors=GREENS((i+1)/num)) 75 | y_ticks.append(H_OFFSET + 2*i*H_FACTOR + H_FACTOR / 2) 76 | ax.broken_barh([(calc_times[i][0], calc_times[i][1] - calc_times[i][0])], 77 | ((2*num-1+2*i) * H_FACTOR + H_OFFSET + H_DIST, H_FACTOR), 78 | facecolors=REDS((i+1)/num)) 79 | x_ticks.append(calc_times[i][0]) 80 | x_ticks.append(calc_times[i][1]) 81 | y_ticks.append((2*num-1+2*i) * H_FACTOR + H_OFFSET + H_DIST + H_FACTOR/ 2) 82 | 83 | x_ticks = np.unique(sorted(x_ticks)) 84 | y_ticks = sorted(y_ticks) 85 | x_ticklabels = ['{:.1f}'.format(x_tick) for x_tick in x_ticks] 86 | 87 | ax.set_title(schd + '_' + str(n) + ' (total error = {} secs)'.format(total_err)) 88 | ax.set_xlabel('secs since start') 89 | ax.xaxis.set_label_coords(0.5, -0.12) 90 | ax.set_ylabel('process names (our results v.s. ground truth)') 91 | 92 | ax.set_xticks(x_ticks) 93 | x_labels = ax.set_xticklabels(x_ticklabels, rotation=0) 94 | for i, x_label in enumerate(x_labels): 95 | x_label.set_y(x_label.get_position()[1] - (i % 3) * 0.032) 96 | ax.set_yticks(y_ticks) 97 | ax.set_yticklabels(y_ticklabels * 2) 98 | ax.grid(True) 99 | 100 | plt.tight_layout() 101 | # plt.show() 102 | plt.savefig('imgs/' + schd + '_' + str(n) + '.png') 103 | # exit() 104 | -------------------------------------------------------------------------------- /process.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | // #define __USE_GNU 3 | 4 | #include 5 | #include 6 | #include 7 | #include "include/common.h" 8 | 9 | static int string_to_int(char *s) { // base-10 10 | int res = 0; 11 | for (; *s; s++) 12 | res = res * 10 + (*s - '0'); 13 | return res; 14 | } 15 | 16 | int main(int argc, char **argv) { 17 | 18 | if (argc != 4) { 19 | fprintf(stderr, "usage: ./this_program process_name process_idx exec_time\n"); 20 | return 0; 21 | } 22 | 23 | pid_t pid = getpid(); 24 | 25 | char *name = argv[1]; 26 | int idx = string_to_int(argv[2]); 27 | int exec_time = string_to_int(argv[3]); 28 | 29 | printf("%s %d\n", name, pid); 30 | // fprintf(stderr, "[%d]%s %d\n", pid, name, exec_time); 31 | 32 | long start_time = syscall(352); 33 | for (int i = 0; i < exec_time; i++) 34 | unit_time(); 35 | long end_time = syscall(352); 36 | 37 | syscall(351, pid, start_time, end_time, 11111); 38 | static const long BASE = 1000000000; 39 | fprintf(stderr, "[Project1] %d %ld.%09ld %ld.%09ld\n", idx, start_time / BASE, start_time % BASE, end_time / BASE, end_time % BASE); 40 | // printf("[Project1] %d %ld.%09ld %ld.%09ld\n", pid, start_time / BASE, start_time % BASE, end_time / BASE, end_time % BASE); 41 | 42 | // fprintf(stderr, "[%d]finish\n", pid); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /report.md: -------------------------------------------------------------------------------- 1 | # 2019 Operating System Project 1 - Process Scheduling 2 | 3 | ## Member 4 | 5 | * 資工二 b06902093 王彥仁 6 | * 寫kernel code、編譯kernel 7 | * RR、SJF、PSJF實作 8 | * 比較與分析效能 9 | * 資工二 b06902026 吳秉柔 10 | * 提供PSJF的原理與實作方式 11 | * 設計執行框架 12 | * FIFO實作 13 | * 程式碼整理與排版 14 | * 資工二 b06902041 吳采耘 15 | * 提供RR的原理與實作方式 16 | * 資工二 b06902054 蔡宥杏 17 | * 提供SJF的原理與實作方式 18 | * 醫學三 b05401009 謝德威 19 | * 提供FIFO的原理與實作方式 20 | * 電機五 b03901056 孫凡耕 21 | * 檢查各實作細節 22 | * 計算理論最優解與誤差 23 | * 比較與分析效能 24 | 25 | ## Design 26 | 27 | ### First-Come, First-Served Scheduling 28 | 29 | * 原理 30 | * 顧名思義,對於每個process,先來的先執行。 31 | * 執行方式 32 | * 將所有process按照ready time由小到大排序。 33 | * 對於每個process,若其ready time為當前的時間,則將該process放入一個queue中。 34 | * 如果目前沒有在執行process,並且queue中有process,則從queue中取出process並執行,直到該process執行結束。 35 | * 執行中的process會被賦予一個較高的priotity。 36 | ``` 37 | change_priority() { 38 | if (no process is running) and (there exist runnable processes): 39 | run the next process; 40 | else if (some process is running) and (there exist other runnable proccess): 41 | increase the priority of the next process; 42 | } 43 | 44 | SIGCHLD_signal_handler() { 45 | wait for completed child process; 46 | number of finished processes += 1; 47 | pop one process from queue; 48 | if (number of finished processes == number of processes): 49 | exit(); 50 | } 51 | 52 | FIFO() { 53 | sort(comingProcess); 54 | change SIGCHLD from block to receive; 55 | while unfinished tasks exist: 56 | change_priority(); 57 | for all (processes that are ready at this moment t): 58 | create process (fork and execute); 59 | push the next ready process into queue; 60 | change_priority(); 61 | run a unit of time; 62 | } 63 | ``` 64 | * 參考資料 65 | * Operating System Concepts Ch.3, Ch.5 66 | 67 | 68 | 69 | ### Round-Robin Scheduling 70 | 71 | * 原理 72 | * 利用計時器固定週期,讓正在執行的process在執行一個週期後進入queue中,並從queue中選定下一個執行的process。 73 | * 執行方式 74 | * 將所有process按照ready time由小到大排序。 75 | * 於每個process,若其ready time為當前的時間,則將該process放入一個queue中。 76 | * 如果目前沒有在執行process,並且queue中有process,則從queue中取出process執行,並計算該process是否會在此執行周期內執行結束。如果沒有結束,在執行一個周期後將remaining execution time減少一個週期,並將該process放入queue中。 77 | * 執行中的process會被賦予一個較高的priotity。 78 | 79 | ``` 80 | change_priority() { 81 | if (no process is running) and (there exist runnable processes): 82 | run the next process; 83 | else if (some process is running) and (there exist other runnable proccess): 84 | increase the priority of the next process; 85 | } 86 | 87 | SIGCHLD_signal_handler() { 88 | wait for completed child process; 89 | number of finished processes += 1; 90 | pop one process from queue; 91 | run = FALSE; 92 | counting_time = 0; 93 | if (number of finished processes == number of processes): 94 | exit(); 95 | } 96 | 97 | RR() { 98 | sort(comingProcess); 99 | change SIGCHLD from block to receive; 100 | while unfinished tasks exist: 101 | change_priority(); 102 | for all (processes that are ready at this moment t): 103 | create process (fork and execute); 104 | push the next ready process into queue; 105 | change_priority(); 106 | run a unit of time; 107 | counting_time++; 108 | if (run == TRUE and counting_time == time_quantum): 109 | pop one process from queue; 110 | expected remaining time of process -= time_quantum; 111 | set the priority of the process to LOW; 112 | push the process back to queue; 113 | run = FALSE; 114 | change_priority(); 115 | } 116 | 117 | ``` 118 | * 參考資料 119 | * [05. 行程排班/排程 (Process Scheduling)](https://sls.weco.net/node/21325) 120 | * [Round-robin排程(作業系統)](https://tw.answers.yahoo.com/question/index?qid=20110602000010KK06795) 121 | 122 | 123 | 124 | ### Shortest Job First (SJF) 125 | 126 | * 原理概念 127 | * 選擇執行時間最短的process來執行,於實際應用的困難點在於如何估算process所需的執行時間。此處應用的SJF是non-preemptive的,不中斷仍在執行的task,另外有PSJF。 128 | * 執行方式 129 | * 將所有process照ready time由小到大排序,若ready time相同,再按照execution time由小到大排序。 130 | * 對於每個process,若其ready time為當前的時間,則將該process放入一個heap中,此heap是照execution time由小到大排序的。 131 | * 如果目前沒有在執行process,並且heap中有process,則取出execution time最小的process並執行,直到該process執行結束。 132 | * 執行中的process會被賦予一個較高的priotity。 133 | ``` 134 | change_priority() { 135 | if (no process is running) and (there exist runnable processes): 136 | run the next process; 137 | else if (some process is running) and (there exist other runnable proccess): 138 | increase the priority of the next process; 139 | } 140 | 141 | SIGCHLD_signal_handler() { 142 | wait for completed child process; 143 | number of finished processes += 1; 144 | run = FALSE; 145 | if (number of finished processes == number of processes): 146 | exit(); 147 | } 148 | 149 | SJF() { 150 | sort(comingProcess) by execute time; 151 | sort(comimgProcess) by ready time; 152 | change SIGCHLD from block to receive; 153 | while unfinished tasks exist: 154 | change_priority(); 155 | for all (processes that are ready at this moment t): 156 | decrease the priority of the next process; 157 | create process (fork and execute); 158 | insert the next ready process into heap; 159 | change_priority(); 160 | run a unit of time; 161 | } 162 | 163 | ``` 164 | * 參考 165 | * [行程排班/排程 (Process Scheduling)](https://sls.weco.net/node/21325) 166 | 167 | 168 | 169 | ### Preemptive Shortest Job First (PSJF) 170 | 171 | * 原理概念 172 | * 每次選擇剩餘執行時間最短的 process 來執行,當新產生的 process 執行時間更短時,就可以插隊。 173 | * 執行方式 174 | * 將所有process照ready time由小到大排序,若ready time相同,再按照execution time由小到大排序。 175 | * 對於每個process,若其ready time為當前的時間,則將該process放入一個heap中,此heap是照remaining execution time由小到大排序的。 176 | * 若當前heap頂端process的remaining execution time比目前執行中的process更小,則將當前執行的process換成該從heap取出的process,並將原本執行的process放入heap中。 177 | * 如果目前沒有執行任何process,並且heap中有process,則取出execution time最小的process執行。 178 | * 執行中的process會被賦予一個較高的priotity。 179 | ``` 180 | change_priority() { 181 | if (no process is running) and (there exist runnable processes): 182 | run the next process; 183 | else if (some process is running) and (there exist other runnable proccess): 184 | increase the priority of the next process; 185 | } 186 | 187 | SIGCHLD_signal_handler() { 188 | wait for completed child process; 189 | number of finished processes += 1; 190 | run = FALSE; 191 | if (number of finished processes == number of processes): 192 | exit(); 193 | } 194 | 195 | PSJF() { 196 | sort(comingProcess) by execute time; 197 | sort(comimgProcess) by ready time; 198 | change SIGCHLD from block to receive; 199 | while unfinished tasks exist: 200 | change_priority(); 201 | for all (processes that are ready at this moment t): 202 | //block SIGCHLD in the functions to avoid race conditions 203 | decrease the priority of the next 2 process; 204 | create process (fork and execute); 205 | insert the next ready process into heap; 206 | change_priority(); 207 | run a unit of time; 208 | check if any child process died when SIGCHLD was blocked; 209 | } 210 | ``` 211 | ## Test & Analysis 212 | 213 | ### FIFO 214 | #### 測試資料1 215 | 資料內容: 216 | ``` 217 | FIFO 218 | 5 219 | P1 0 500 220 | P2 0 500 221 | P3 0 500 222 | P4 0 500 223 | P5 0 500 224 | ``` 225 | 執行結果: 226 | ``` 227 | P1 1030 228 | P2 1031 229 | P3 1032 230 | P4 1033 231 | P5 1034 232 | [Project1] 1030 1556267696.005955744 1556267697.447623058 233 | [Project1] 1031 1556267697.448563280 1556267698.887764870 234 | [Project1] 1032 1556267698.888653958 1556267700.375917190 235 | [Project1] 1033 1556267700.377058738 1556267701.881777997 236 | [Project1] 1034 1556267701.882504746 1556267703.341983999 237 | ``` 238 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 239 | ![](https://i.imgur.com/hZF108V.png) 240 | 241 | #### 測試資料2 242 | 資料內容: 243 | ``` 244 | FIFO 245 | 4 246 | P1 0 80000 247 | P2 100 5000 248 | P3 200 1000 249 | P4 300 1000 250 | ``` 251 | 執行結果: 252 | ``` 253 | P1 3169 254 | P2 3170 255 | P3 3174 256 | P4 3175 257 | [Project1] 3169 1556267703.356366380 1556267937.327534262 258 | [Project1] 3170 1556267937.328329747 1556267951.732974392 259 | [Project1] 3174 1556267951.733685676 1556267954.660797710 260 | [Project1] 3175 1556267954.662715126 1556267957.544203414 261 | ``` 262 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 263 | ![](https://i.imgur.com/qt3epoS.png) 264 | 265 | 266 | #### 測試資料3 267 | 資料內容: 268 | ``` 269 | FIFO 270 | 7 271 | P1 0 8000 272 | P2 200 5000 273 | P3 300 3000 274 | P4 400 1000 275 | P5 500 1000 276 | P6 500 1000 277 | P7 600 4000 278 | ``` 279 | 執行結果: 280 | ``` 281 | P1 4114 282 | P2 4118 283 | P3 4119 284 | P4 4120 285 | P5 4124 286 | P6 4125 287 | P7 4126 288 | [Project1] 4114 1556267957.557357029 1556267981.033809368 289 | [Project1] 4118 1556267981.034554538 1556267995.795331824 290 | [Project1] 4119 1556267995.796093011 1556268004.546408140 291 | [Project1] 4120 1556268004.547211199 1556268007.492391289 292 | [Project1] 4124 1556268007.493287372 1556268010.434410310 293 | [Project1] 4125 1556268010.435314787 1556268013.401105627 294 | [Project1] 4126 1556268013.401778201 1556268025.149761910 295 | ``` 296 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 297 | ![](https://i.imgur.com/Oo81ham.png) 298 | 299 | 300 | #### 測試資料4 301 | 資料內容: 302 | ``` 303 | FIFO 304 | 4 305 | P1 0 2000 306 | P2 500 500 307 | P3 500 200 308 | P4 1500 500 309 | ``` 310 | 執行結果: 311 | ``` 312 | P1 4448 313 | P2 4452 314 | P3 4453 315 | P4 4463 316 | [Project1] 4448 1556281099.394525838 1556281105.172335335 317 | [Project1] 4452 1556281105.173256408 1556281106.611718370 318 | [Project1] 4453 1556281106.612488762 1556281107.192480105 319 | [Project1] 4463 1556281107.193478191 1556281108.657068430 320 | ``` 321 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 322 | ![](https://i.imgur.com/CUXJqJw.png) 323 | 324 | 325 | #### 測試資料5 326 | 資料內容: 327 | ``` 328 | FIFO 329 | 7 330 | P1 0 8000 331 | P2 200 5000 332 | P3 200 3000 333 | P4 400 1000 334 | P5 400 1000 335 | P6 600 1000 336 | P7 600 4000 337 | ``` 338 | 執行結果: 339 | ``` 340 | P1 4762 341 | P2 4763 342 | P3 4764 343 | P4 4768 344 | P5 4769 345 | P6 4770 346 | P7 4771 347 | [Project1] 4762 1556268034.513253253 1556268057.593677271 348 | [Project1] 4763 1556268057.594464663 1556268072.202658653 349 | [Project1] 4764 1556268072.203379298 1556268081.023290764 350 | [Project1] 4768 1556268081.023870239 1556268083.954713381 351 | [Project1] 4769 1556268083.955627959 1556268086.854611338 352 | [Project1] 4770 1556268086.855351215 1556268089.777458667 353 | [Project1] 4771 1556268089.778370442 1556268101.602077366 354 | ``` 355 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 356 | ![](https://i.imgur.com/35ooqqZ.png) 357 | 358 | 359 | ### RR 360 | #### 測試資料1 361 | 資料內容: 362 | ``` 363 | RR 364 | 5 365 | P1 0 500 366 | P2 0 500 367 | P3 0 500 368 | P4 0 500 369 | P5 0 500 370 | ``` 371 | 執行結果: 372 | ``` 373 | P1 5371 374 | P2 5372 375 | P3 5373 376 | P4 5374 377 | P5 5375 378 | [Project1] 5371 1556267012.172391630 1556267013.636782768 379 | [Project1] 5372 1556267013.637596962 1556267015.144664635 380 | [Project1] 5373 1556267015.145695418 1556267016.630127328 381 | [Project1] 5374 1556267016.631057233 1556267018.118905020 382 | [Project1] 5375 1556267018.119639198 1556267019.557252571 383 | ``` 384 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 385 | ![](https://i.imgur.com/qhG5AeJ.png) 386 | 387 | 388 | #### 測試資料2 389 | 資料內容: 390 | ``` 391 | RR 392 | 2 393 | P1 600 4000 394 | P2 800 5000 395 | ``` 396 | 執行結果: 397 | ``` 398 | P1 5565 399 | P2 5569 400 | [Project1] 5565 1556267021.356233936 1556267043.244070124 401 | [Project1] 5569 1556267022.789869600 1556267047.521132718 402 | ``` 403 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 404 | ![](https://i.imgur.com/KHhCjlf.png) 405 | 406 | 407 | #### 測試資料3 408 | 資料內容: 409 | ``` 410 | RR 411 | 6 412 | P1 1200 5000 413 | P2 2400 4000 414 | P3 3600 3000 415 | P4 4800 7000 416 | P5 5200 6000 417 | P6 5800 5000 418 | ``` 419 | 執行結果: 420 | ``` 421 | P1 5693 422 | P2 5706 423 | P3 5718 424 | P4 5731 425 | P5 5735 426 | P6 5742 427 | [Project1] 5718 1556267059.666615102 1556267100.587747789 428 | [Project1] 5693 1556267051.026896095 1556267103.548607283 429 | [Project1] 5706 1556267055.328398416 1556267106.488141589 430 | [Project1] 5742 1556267071.301305316 1556267129.855954499 431 | [Project1] 5735 1556267068.404326454 1556267135.761305332 432 | [Project1] 5731 1556267065.451713173 1556267138.594189703 433 | ``` 434 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 435 | ![](https://i.imgur.com/H11TA0H.png) 436 | 437 | 438 | #### 測試資料4 439 | 資料內容: 440 | ``` 441 | RR 442 | 7 443 | P1 0 8000 444 | P2 200 5000 445 | P3 300 3000 446 | P4 400 1000 447 | P5 500 1000 448 | P6 500 1000 449 | P7 600 4000 450 | ``` 451 | 執行結果: 452 | ``` 453 | P1 6712 454 | P2 6713 455 | P3 6717 456 | P4 6718 457 | P5 6719 458 | P6 6720 459 | P7 6724 460 | [Project1] 6718 1556267143.030088707 1556267154.775837897 461 | [Project1] 6719 1556267145.963340497 1556267157.761930919 462 | [Project1] 6720 1556267147.398581715 1556267159.170775836 463 | [Project1] 6717 1556267141.533656823 1556267181.354278683 464 | [Project1] 6724 1556267148.892808209 1556267193.038339364 465 | [Project1] 6713 1556267140.046027846 1556267197.514231450 466 | [Project1] 6712 1556267138.621823815 1556267206.420814624 467 | ``` 468 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 469 | ![](https://i.imgur.com/GgiodyK.png) 470 | 471 | 472 | #### 測試資料5 473 | 資料內容: 474 | ``` 475 | RR 476 | 7 477 | P1 0 8000 478 | P2 200 5000 479 | P3 200 3000 480 | P4 400 1000 481 | P5 400 1000 482 | P6 600 1000 483 | P7 600 4000 484 | ``` 485 | 執行結果: 486 | ``` 487 | P1 8222 488 | P2 8226 489 | P3 8227 490 | P4 8228 491 | P5 8229 492 | P6 8233 493 | P7 8234 494 | [Project1] 8228 1556267210.776174471 1556267222.339916321 495 | [Project1] 8229 1556267212.202524675 1556267223.846046997 496 | [Project1] 8233 1556267215.052176172 1556267226.813624358 497 | [Project1] 8227 1556267209.326543274 1556267248.933188703 498 | [Project1] 8234 1556267216.491265951 1556267260.721219795 499 | [Project1] 8226 1556267207.897662196 1556267264.928738340 500 | [Project1] 8222 1556267206.440100595 1556267273.542002480 501 | ``` 502 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 503 | ![](https://i.imgur.com/odIDdsY.png) 504 | 505 | 506 | ### SJF 507 | #### 測試資料1 508 | 資料內容: 509 | ``` 510 | SJF 511 | 4 512 | P1 0 7000 513 | P2 0 2000 514 | P3 100 1000 515 | P4 200 4000 516 | ``` 517 | 執行結果: 518 | ``` 519 | P2 9036 520 | P1 9037 521 | P3 9041 522 | P4 9042 523 | [Project1] 9036 1556267273.563992439 1556267279.345748769 524 | [Project1] 9041 1556267279.346689060 1556267282.255005355 525 | [Project1] 9042 1556267282.255746710 1556267293.985676622 526 | [Project1] 9037 1556267293.986441521 1556267314.813214073 527 | ``` 528 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 529 | ![](https://i.imgur.com/JPFLGbb.png) 530 | 531 | 532 | #### 測試資料2 533 | 資料內容: 534 | ``` 535 | SJF 536 | 5 537 | P1 100 100 538 | P2 100 4000 539 | P3 200 200 540 | P4 200 4000 541 | P5 200 7000 542 | ``` 543 | 執行結果: 544 | ``` 545 | P1 9449 546 | P3 9450 547 | P2 9454 548 | P4 9455 549 | P5 9456 550 | [Project1] 9449 1556273082.261394371 1556273082.578534405 551 | [Project1] 9450 1556273082.579450508 1556273083.175679321 552 | [Project1] 9454 1556273083.176759269 1556273095.037849678 553 | [Project1] 9455 1556273095.038662587 1556273106.628237103 554 | [Project1] 9456 1556273106.629285202 1556273126.852447988 555 | ``` 556 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 557 | ![](https://i.imgur.com/ClIj8xl.png) 558 | 559 | 560 | #### 測試資料3 561 | 資料內容: 562 | ``` 563 | SJF 564 | 8 565 | P1 100 3000 566 | P2 100 5000 567 | P3 100 7000 568 | P4 200 10 569 | P5 200 10 570 | P6 300 4000 571 | P7 400 4000 572 | P8 500 9000 573 | ``` 574 | 執行結果: 575 | ``` 576 | P1 11501 577 | P4 11504 578 | P5 11505 579 | P6 11506 580 | P7 11507 581 | P2 11502 582 | P3 11503 583 | P8 11511 584 | [Project1] 11501 1556267359.672181839 1556267368.468376440 585 | [Project1] 11504 1556267368.469405546 1556267368.499879461 586 | [Project1] 11505 1556267368.500644831 1556267368.531903565 587 | [Project1] 11506 1556267368.532659705 1556267380.221958006 588 | [Project1] 11507 1556267380.222597346 1556267392.072762336 589 | [Project1] 11502 1556267392.073620507 1556267406.700528466 590 | [Project1] 11503 1556267406.701579939 1556267427.329905502 591 | [Project1] 11511 1556267427.330569346 1556267453.395551434 592 | ``` 593 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 594 | ![](https://i.imgur.com/Z8yg8LM.png) 595 | 596 | 597 | #### 測試資料4 598 | 資料內容: 599 | ``` 600 | SJF 601 | 5 602 | P1 0 3000 603 | P2 1000 1000 604 | P3 2000 4000 605 | P4 5000 2000 606 | P5 7000 1000 607 | ``` 608 | 執行結果: 609 | ``` 610 | P1 16501 611 | P2 16511 612 | P3 16521 613 | P5 16565 614 | P4 16549 615 | [Project1] 16501 1556267453.423024637 1556267462.192598479 616 | [Project1] 16511 1556267462.194584693 1556267465.098985788 617 | [Project1] 16521 1556267465.099863826 1556267476.652149328 618 | [Project1] 16565 1556267476.653164431 1556267479.553047282 619 | [Project1] 16549 1556267479.553812300 1556267485.353083034 620 | ``` 621 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 622 | ![](https://i.imgur.com/rQiHiwY.png) 623 | 624 | 625 | #### 測試資料5 626 | 資料內容: 627 | ``` 628 | SJF 629 | 4 630 | P1 0 2000 631 | P2 500 500 632 | P3 1000 500 633 | P4 1500 500 634 | ``` 635 | 執行結果: 636 | ``` 637 | P1 16893 638 | P2 16900 639 | P3 16904 640 | P4 16911 641 | [Project1] 16893 1556267485.363140018 1556267491.273938096 642 | [Project1] 16900 1556267491.274883902 1556267492.713872845 643 | [Project1] 16904 1556267492.714582136 1556267494.157116128 644 | [Project1] 16911 1556267494.157999645 1556267495.612737337 645 | ``` 646 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 647 | ![](https://i.imgur.com/Qbq4kTy.png) 648 | 649 | 650 | ### PSJF 651 | #### 測試資料1 652 | 資料內容: 653 | ``` 654 | PSJF 655 | 4 656 | P1 0 10000 657 | P2 1000 7000 658 | P3 2000 5000 659 | P4 3000 3000 660 | ``` 661 | 執行結果: 662 | ``` 663 | P1 17182 664 | P2 17192 665 | P3 17202 666 | P4 17212 667 | [Project1] 17212 1556267504.357288589 1556267513.077936866 668 | [Project1] 17202 1556267501.409855706 1556267524.696781902 669 | [Project1] 17192 1556267498.485999811 1556267542.101250387 670 | [Project1] 17182 1556267495.622864163 1556267568.145374822 671 | ``` 672 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 673 | ![](https://i.imgur.com/LGtb5ss.png) 674 | 675 | 676 | #### 測試資料2 677 | 資料內容: 678 | ``` 679 | PSJF 680 | 5 681 | P1 0 3000 682 | P2 1000 1000 683 | P3 2000 4000 684 | P4 5000 2000 685 | P5 7000 1000 686 | ``` 687 | 執行結果: 688 | ``` 689 | P1 17480 690 | P2 17487 691 | P3 17497 692 | P4 17527 693 | P5 17546 694 | [Project1] 17487 1556267571.054433036 1556267574.009092155 695 | [Project1] 17480 1556267568.180510843 1556267579.910755765 696 | [Project1] 17527 1556267582.748044684 1556267588.574176808 697 | [Project1] 17546 1556267588.637914347 1556267591.562909837 698 | [Project1] 17497 1556267579.911440537 1556267600.309033345 699 | ``` 700 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 701 | ![](https://i.imgur.com/106kAEm.png) 702 | 703 | 704 | #### 測試資料3 705 | 資料內容: 706 | ``` 707 | PSJF 708 | 4 709 | P1 0 2000 710 | P2 500 500 711 | P3 1000 500 712 | P4 1500 500 713 | ``` 714 | 執行結果: 715 | ``` 716 | P1 17625 717 | P2 17629 718 | P3 17636 719 | P4 17640 720 | [Project1] 17629 1556267601.726423729 1556267603.201099864 721 | [Project1] 17636 1556267603.201947820 1556267604.618702682 722 | [Project1] 17640 1556267604.619486251 1556267606.076288554 723 | [Project1] 17625 1556267600.322827757 1556267610.394578261 724 | ``` 725 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 726 | ![](https://i.imgur.com/HLxSr6o.png) 727 | 728 | 729 | #### 測試資料4 730 | 資料內容: 731 | ``` 732 | PSJF 733 | 4 734 | P1 0 7000 735 | P2 0 2000 736 | P3 100 1000 737 | P4 200 4000 738 | ``` 739 | 執行結果: 740 | ``` 741 | P2 17740 742 | P3 17742 743 | P4 17743 744 | P1 17741 745 | [Project1] 17742 1556267610.695144441 1556267613.595471794 746 | [Project1] 17740 1556267610.405662588 1556267619.054863255 747 | [Project1] 17743 1556267619.055766535 1556267630.625824266 748 | [Project1] 17741 1556267630.626792157 1556267651.026717751 749 | ``` 750 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 751 | ![](https://i.imgur.com/CCZAiPP.png) 752 | 753 | 754 | #### 測試資料5 755 | 資料內容: 756 | ``` 757 | PSJF 758 | 5 759 | P1 100 100 760 | P2 100 4000 761 | P3 200 200 762 | P4 200 4000 763 | P5 200 7000 764 | ``` 765 | 執行結果: 766 | ``` 767 | P1 17921 768 | P3 17923 769 | P2 17922 770 | P4 17924 771 | P5 17925 772 | [Project1] 17921 1556273200.242746796 1556273200.528447951 773 | [Project1] 17923 1556273200.534993404 1556273201.109025057 774 | [Project1] 17922 1556273200.529555476 1556273212.639375820 775 | [Project1] 17924 1556273212.640065418 1556273224.173449223 776 | [Project1] 17925 1556273224.174105085 1556273244.520677485 777 | ``` 778 | 與理論解的比較圖(上半為理論解,下半為我們的結果): 779 | ![](https://i.imgur.com/H3FGcXA.png) 780 | 781 | 782 | ## Conclusion 783 | 784 | 在實際執行時,我們發現若使用三種priority給予不同狀態的程序,可以讓程序間的銜接最好,同時也較容易進行排程管理。priority的分級如下: 785 | 1. 執行中的process:最高的priority 786 | 2. 下一個準備執行的prcess:第二高的priority 787 | 3. 其餘的process:最低的priority 788 | 789 | 經過分析,我們認為理論與實際的差異主要來自於以下三點: 790 | 1. scheduler 除了排程外,還有其他執行所花費的時間,例如動態調整各process的priority、執行新的process與資料結構的操作等。 791 | 2. 同樣執行 1000000 次迴圈,但 CPU 所花費的時間不完全一樣,除了各process執行迴圈的單位時間不相同外,scheduler的計時器也不會完全和process的同步,進而造成排程上的誤差。 792 | 3. 因為電腦上不只有我們的程序,所以有可能我們的程序因為context switch而被中斷,然而我們的計時不會跟著扣掉,因此造成程序執行時間增加。 793 | -------------------------------------------------------------------------------- /scheduler.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "include/common.h" 8 | #include "include/priority.h" 9 | 10 | int main() { 11 | 12 | char scheduling_policy[MAX_SCHEDULE_NAME]; 13 | assert(scanf("%s", scheduling_policy) == 1); 14 | 15 | const char scheduling_types[NUM_SCHEDULING_TYPE][MAX_SCHEDULE_NAME] 16 | = { "FIFO", "RR", "SJF", "PSJF" }; 17 | 18 | for (int i = 0; i <= NUM_SCHEDULING_TYPE; ++i) { 19 | if (i == NUM_SCHEDULING_TYPE) { 20 | fprintf(stderr, "no such scheduling type\n"); 21 | return 1; 22 | } 23 | if (strcmp(scheduling_policy, scheduling_types[i]) == 0) break; 24 | } 25 | 26 | USE_CPU(getpid(), 0); 27 | SET_PRIORITY(getpid(), SCHED_FIFO, PRIORITY_INIT); 28 | 29 | fflush(stdin); 30 | switch(scheduling_policy[0]) { 31 | case 'F': 32 | execl("./FIFO", "./FIFO", (char *)0); 33 | break; 34 | case 'R': 35 | execl("./RR", "./RR", (char *)0); 36 | break; 37 | case 'S': 38 | execl("./SJF", "./SJF", (char *)0); 39 | break; 40 | case 'P': 41 | execl("./PSJF", "./PSJF", (char *)0); 42 | break; 43 | } 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /test/FIFO_1.txt: -------------------------------------------------------------------------------- 1 | FIFO 2 | 5 3 | P1 0 500 4 | P2 0 500 5 | P3 0 500 6 | P4 0 500 7 | P5 0 500 -------------------------------------------------------------------------------- /test/FIFO_2.txt: -------------------------------------------------------------------------------- 1 | FIFO 2 | 4 3 | P1 0 80000 4 | P2 100 5000 5 | P3 200 1000 6 | P4 300 1000 -------------------------------------------------------------------------------- /test/FIFO_3.txt: -------------------------------------------------------------------------------- 1 | FIFO 2 | 7 3 | P1 0 8000 4 | P2 200 5000 5 | P3 300 3000 6 | P4 400 1000 7 | P5 500 1000 8 | P6 500 1000 9 | P7 600 4000 10 | -------------------------------------------------------------------------------- /test/FIFO_4.txt: -------------------------------------------------------------------------------- 1 | FIFO 2 | 4 3 | P1 0 2000 4 | P2 500 500 5 | P3 500 200 6 | P4 1500 500 7 | -------------------------------------------------------------------------------- /test/FIFO_5.txt: -------------------------------------------------------------------------------- 1 | FIFO 2 | 7 3 | P1 0 8000 4 | P2 200 5000 5 | P3 200 3000 6 | P4 400 1000 7 | P5 400 1000 8 | P6 600 1000 9 | P7 600 4000 10 | -------------------------------------------------------------------------------- /test/PSJF_1.txt: -------------------------------------------------------------------------------- 1 | PSJF 2 | 4 3 | P1 0 10000 4 | P2 1000 7000 5 | P3 2000 5000 6 | P4 3000 3000 7 | -------------------------------------------------------------------------------- /test/PSJF_2.txt: -------------------------------------------------------------------------------- 1 | PSJF 2 | 5 3 | P1 0 3000 4 | P2 1000 1000 5 | P3 2000 4000 6 | P4 5000 2000 7 | P5 7000 1000 -------------------------------------------------------------------------------- /test/PSJF_3.txt: -------------------------------------------------------------------------------- 1 | PSJF 2 | 4 3 | P1 0 2000 4 | P2 500 500 5 | P3 1000 500 6 | P4 1500 500 7 | -------------------------------------------------------------------------------- /test/PSJF_4.txt: -------------------------------------------------------------------------------- 1 | PSJF 2 | 4 3 | P1 0 7000 4 | P2 0 2000 5 | P3 100 1000 6 | P4 200 4000 7 | -------------------------------------------------------------------------------- /test/PSJF_5.txt: -------------------------------------------------------------------------------- 1 | PSJF 2 | 5 3 | P1 100 100 4 | P2 100 4000 5 | P3 200 200 6 | P4 200 4000 7 | P5 200 7000 -------------------------------------------------------------------------------- /test/RR_1.txt: -------------------------------------------------------------------------------- 1 | RR 2 | 5 3 | P1 0 500 4 | P2 0 500 5 | P3 0 500 6 | P4 0 500 7 | P5 0 500 -------------------------------------------------------------------------------- /test/RR_2.txt: -------------------------------------------------------------------------------- 1 | RR 2 | 2 3 | P1 600 4000 4 | P2 800 5000 5 | -------------------------------------------------------------------------------- /test/RR_3.txt: -------------------------------------------------------------------------------- 1 | RR 2 | 6 3 | P1 1200 5000 4 | P2 2400 4000 5 | P3 3600 3000 6 | P4 4800 7000 7 | P5 5200 6000 8 | P6 5800 5000 9 | -------------------------------------------------------------------------------- /test/RR_4.txt: -------------------------------------------------------------------------------- 1 | RR 2 | 7 3 | P1 0 8000 4 | P2 200 5000 5 | P3 300 3000 6 | P4 400 1000 7 | P5 500 1000 8 | P6 500 1000 9 | P7 600 4000 10 | -------------------------------------------------------------------------------- /test/RR_5.txt: -------------------------------------------------------------------------------- 1 | RR 2 | 7 3 | P1 0 8000 4 | P2 200 5000 5 | P3 200 3000 6 | P4 400 1000 7 | P5 400 1000 8 | P6 600 1000 9 | P7 600 4000 10 | -------------------------------------------------------------------------------- /test/SJF_1.txt: -------------------------------------------------------------------------------- 1 | SJF 2 | 4 3 | P1 0 7000 4 | P2 0 2000 5 | P3 100 1000 6 | P4 200 4000 7 | -------------------------------------------------------------------------------- /test/SJF_2.txt: -------------------------------------------------------------------------------- 1 | SJF 2 | 5 3 | P1 100 100 4 | P2 100 4000 5 | P3 200 200 6 | P4 200 4000 7 | P5 200 7000 -------------------------------------------------------------------------------- /test/SJF_3.txt: -------------------------------------------------------------------------------- 1 | SJF 2 | 8 3 | P1 100 3000 4 | P2 100 5000 5 | P3 100 7000 6 | P4 200 10 7 | P5 200 10 8 | P6 300 4000 9 | P7 400 4000 10 | P8 500 9000 -------------------------------------------------------------------------------- /test/SJF_4.txt: -------------------------------------------------------------------------------- 1 | SJF 2 | 5 3 | P1 0 3000 4 | P2 1000 1000 5 | P3 2000 4000 6 | P4 5000 2000 7 | P5 7000 1000 -------------------------------------------------------------------------------- /test/SJF_5.txt: -------------------------------------------------------------------------------- 1 | SJF 2 | 4 3 | P1 0 2000 4 | P2 500 500 5 | P3 1000 500 6 | P4 1500 500 7 | -------------------------------------------------------------------------------- /test/pj1_test.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangyenjen/OS2019-Process_Scheduling/9def1fa96eaacb790ee6e5a23948280e9d1bb8a9/test/pj1_test.zip --------------------------------------------------------------------------------