I've been reviewing the operating system recently, and I have the following knowledge points:
1) Process scheduling algorithm: it adopts os scheduling algorithm (i.e. assigning the processor to the process with the highest priority) and first come first serve algorithm.
2) Each process is represented by a process control block (PCB). The process control block can contain the following information: process name, priority number, arrival time, required running time, used CPU time, process status, etc.
3) The priority number of processes and the required running time can be manually specified in advance (or generated by random numbers). The arrival time of the process is the time entered by the process. The running time of a process is calculated in time slices.
4) The state of each process can be one of three states: ready W (Wait), running R (Run), or completed F (Finish).
5) After the ready process obtains the CPU, it can only run one time slice. It is represented by CPU time used plus 1. If the occupied CPU time of a process has reached the required running time after running a time slice, the process will be revoked. If the occupied CPU time of the process has not reached the required running time after running a time slice, that is, the process needs to continue running, at this time, the priority of the process should be reduced by 1 (i.e. one level), and then it should be inserted into the ready queue to wait for the CPU.
6) Each time, the scheduler prints the PCB of the running process, ready queue and each process for inspection.
7) Repeat the above process until all the processes are completed.
According to these knowledge points, the following requirements are given in the curriculum design report:
1) Fully understand the design requirements. Deeply understand the concepts of process control block and process queue, and experience and understand the scheduling algorithm of the highest priority number first (i.e. assigning the processor to the process with the highest priority number) and the specific implementation method of the first come first serve algorithm.
2) Decompose the process scheduler as required and decompose it into multiple sub modules according to its functions.
3) Establish the program flow chart of the main control module and the program flow chart of each functional sub module, which shall be clear, simple and complete in function.
4) Compile the main program code and subroutine code according to the flow chart. The program design structure is required to be clear, concise and easy to modify and debug.
5) The above design requires one person to complete the design independently.
6) After the design is completed, the machine shall be put into operation for commissioning.
7) The program runs successfully, then some function tests are carried out, and the practical and special data are selected for input and debugging, so as to further improve and perfect the design.
8) Print out the program running results and analyze the results to verify the correctness of the program design.
To solve the above problems, process programming and coding
The basic knowledge points are as follows:
Static priority, also known as static priority, is determined when the process is created and remains unchanged throughout the operation of the process. Generally, the priority is expressed by an integer in a certain range. For example, an integer in 0 ~ 7 or 0 ~ 255 is also called the priority number, but the specific usage is different: some systems use "0" to represent the highest priority. When the value is larger, the priority is lower; Some systems are just the opposite.
There is no doubt that the simplest CPU scheduling algorithm is the first come first serve (FCFS) scheduling method. With this scheme, the process that requests the CPU first is allocated to the CPU first.
The procedure flow chart is as follows:
The code implementation is as follows:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #define W 1 //Wait #define R 2 //Run #define F 0 //Finsh #define RAND_FLAG_OPEN 0 #define FALSE 0 #define TRUE 1 struct PCB{ char* p_name; //Process name unsigned int priority; //priority long arrive_time; //arrival time long need_time; //Run time required long use_time; //CPU time used unsigned int status; //Process status }; struct PCB_SPACE{ struct PCB data; struct PCB_SPACE* next; }; //Process space initialization of chained storage struct PCB_SPACE* head; struct PCB_SPACE* rear; struct PCB_SPACE* init_process_space(struct PCB_SPACE* head){ head = (struct PCB_SPACE*)malloc(sizeof(struct PCB_SPACE)); rear = (struct PCB_SPACE*)malloc(sizeof(struct PCB_SPACE)); rear = head; return head; } //Get the timestamp of the current system int get_now_time(){ time_t t; t = time(NULL); return time(&t); } struct PCB init_pcb(char* p_name,long need_time,long use_time,unsigned int status,unsigned int priority){ struct PCB p; p.arrive_time = get_now_time(); p.p_name = p_name; p.need_time = need_time%10 + 1; p.use_time = use_time; p.status = status; if(priority == 0){ p.priority = rand()%256; }else{ int number = 0; printf("Please set the process name as%s Priority series of[0-255]:",p_name); scanf("%d",&number); p.priority = number%256; } return p; } struct PCB_SPACE* temp; struct PCB_SPACE* insert_pcb_space(struct PCB p){ temp = (struct PCB_SPACE*)malloc(sizeof(struct PCB_SPACE)); temp->data = p; temp->next = NULL; if(head->next == NULL){ head->next = temp; }else{ rear->next = temp; } rear = temp; return head; } char* itoa(int number){ char* temp = (char*)malloc(sizeof(char)*256); strcpy(temp,"process_"); char* buffer = (char*)malloc(sizeof(char)*256); sprintf(buffer,"%d",number); strcat(temp,buffer); return temp; } void disp(struct PCB_SPACE* head,int len){ struct PCB_SPACE* p = head->next; for(int i =0;i<len;i++){ printf("\r\n"); printf("Process name:%s\r\n",p->data.p_name); printf("Process priority:%u\r\n",(p->data).priority); printf("Process arrival timestamp:%ld\r\n",(p->data).arrive_time); printf("Time the process needs to run:%ld\r\n",(p->data).need_time); printf("Process elapsed time:%ld\r\n",(p->data).use_time); printf("\r\n"); p = p->next; } } //First come first serve algorithm void FCFS(struct PCB_SPACE* head,int len){ int continue_flag = FALSE; struct PCB_SPACE* p = head->next; int ad_count = 0; while(TRUE){ if(p->data.use_time != p->data.need_time && p->data.status == W){ printf("[+]First come first serve algorithm scheduling%s,Run for 1 second,The remaining running time is:%ld second\r\n",p->data.p_name,p->data.need_time - p->data.use_time); p->data.status = R; continue_flag = TRUE; p->data.use_time = p->data.use_time + 1; p->data.status = W; }else{ if(p->data.status != F){ printf("[+]process%s Completed\r\n",p->data.p_name); } p->data.status = F; } p = p->next; ad_count = ad_count + 1; if(ad_count%len == 0){ if(continue_flag == FALSE){ printf("[+]All processes are complete!"); break; }else{ continue_flag = FALSE; } printf("\r\n"); } } } int main(){ int process_number = 0; printf("=============================\r\n"); printf("Start creating process block PCB:\r\n"); printf("Please enter the number of processes to be created:"); scanf("%d",&process_number); head = init_process_space(head); struct PCB p; for(int i = 0;i<process_number;i++){ char* pcb_name = itoa((i+1)); long need_time = rand(); //Try to control the time within 10 seconds and shorten the experimental time long use_time = 0; unsigned int status = W; unsigned int priority = RAND_FLAG_OPEN; p = init_pcb(pcb_name,need_time,use_time,status,priority); insert_pcb_space(p); printf("%s\r\n",p.p_name); } rear->next = head->next; //Form a circular queue, and head Data is empty, so point to head - > next printf("=============================\r\n"); disp(head,process_number); FCFS(head,process_number); //First come first serve algorithm return 0; }
The FCFS strategy can be implemented through the data structure of one-way circular linked list, and the scheduling algorithm is logically similar to a circular queue. When a process enters the ready queue, its PCB will be linked to the end of the queue. When the CPU is idle, it is allocated to the process at the head of the queue, and then the pointer points to the next element in the queue. FCFS scheduling code is simple to write and easy to understand.
Of course, we can't directly think that this is a queue data structure, which is a circular one-way linked list in concrete and logic, but the scheduling algorithm refers to the characteristics of the queue.
According to the above code, we modify FCFS, which is still a circular queue. We sort the elements in the queue and run FCFS according to the priority. Then the result is the highest priority algorithm scheduled according to the priority.
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #define W 1 //Wait #define R 2 //Run #define F 0 //Finsh #define RAND_FLAG_OPEN 0 #define FALSE 0 #define TRUE 1 struct PCB{ char* p_name; //Process name unsigned int priority; //priority long arrive_time; //arrival time long need_time; //Run time required long use_time; //CPU time used unsigned int status; //Process status }; struct PCB_SPACE{ struct PCB data; struct PCB_SPACE* next; }; //Process space initialization of chained storage struct PCB_SPACE* head; struct PCB_SPACE* rear; struct PCB_SPACE* init_process_space(struct PCB_SPACE* head){ head = (struct PCB_SPACE*)malloc(sizeof(struct PCB_SPACE)); rear = (struct PCB_SPACE*)malloc(sizeof(struct PCB_SPACE)); rear = head; return head; } //Get the timestamp of the current system int get_now_time(){ time_t t; t = time(NULL); return time(&t); } struct PCB init_pcb(char* p_name,long need_time,long use_time,unsigned int status,unsigned int priority){ struct PCB p; p.arrive_time = get_now_time(); p.p_name = p_name; p.need_time = need_time%10 + 1; p.use_time = use_time; p.status = status; if(priority == 0){ p.priority = rand()%256; }else{ int number = 0; printf("Please set the process name as%s Priority series of[0-255]:",p_name); scanf("%d",&number); p.priority = number%256; } return p; } struct PCB_SPACE* temp; struct PCB_SPACE* insert_pcb_space(struct PCB p){ temp = (struct PCB_SPACE*)malloc(sizeof(struct PCB_SPACE)); temp->data = p; temp->next = NULL; if(head->next == NULL){ head->next = temp; }else{ rear->next = temp; } rear = temp; return head; } char* itoa(int number){ char* temp = (char*)malloc(sizeof(char)*256); strcpy(temp,"process_"); char* buffer = (char*)malloc(sizeof(char)*256); sprintf(buffer,"%d",number); strcat(temp,buffer); return temp; } void disp(struct PCB_SPACE* head,int len){ struct PCB_SPACE* p = head->next; for(int i =0;i<len;i++){ printf("\r\n"); printf("Process name:%s\r\n",p->data.p_name); printf("Process priority:%u\r\n",(p->data).priority); printf("Process arrival timestamp:%ld\r\n",(p->data).arrive_time); printf("Time the process needs to run:%ld\r\n",(p->data).need_time); printf("Process elapsed time:%ld\r\n",(p->data).use_time); printf("\r\n"); p = p->next; } } //First come first serve algorithm void FCFS(struct PCB_SPACE* head,int len){ int continue_flag = FALSE; struct PCB_SPACE* p = head->next; int ad_count = 0; while(TRUE){ if(p->data.use_time != p->data.need_time && p->data.status == W){ printf("[+]First come first serve algorithm scheduling%s,Run for 1 second,The remaining running time is:%ld second\r\n",p->data.p_name,p->data.need_time - p->data.use_time); //disp(head,len); p->data.status = R; continue_flag = TRUE; p->data.use_time = p->data.use_time + 1; p->data.status = W; }else{ if(p->data.status != F){ printf("[+]process%s Completed\r\n",p->data.p_name); } p->data.status = F; } p = p->next; ad_count = ad_count + 1; if(ad_count%len == 0){ if(continue_flag == FALSE){ printf("[+]All processes are complete!"); break; }else{ continue_flag = FALSE; } printf("\r\n"); } } } //Because you need to judge the priority number and sort the priority void sort(struct PCB_SPACE* head,int len){ struct PCB_SPACE* p = head->next; for(int i =0;i<len-1;i++){ for(int j =0;j<len-1;j++){ struct PCB_SPACE* node1 = p; struct PCB_SPACE* node2 = p->next; if(node1->data.priority > node2->data.priority){ //The smaller the number of priorities, the higher the priority struct PCB temp = node1->data; node1->data = node2->data; node2->data = temp; } } } } void OS_Server(struct PCB_SPACE* head,int len){ sort(head,len); int continue_flag = FALSE; struct PCB_SPACE* p = head->next; int ad_count = 0; while(TRUE){ if(p->data.use_time != p->data.need_time && p->data.status == W){ printf("[+]Highest priority service scheduling algorithm%s,Run for 1 second,The remaining running time is:%ld second\r\n",p->data.p_name,p->data.need_time - p->data.use_time); //disp(head,len); p->data.status = R; continue_flag = TRUE; p->data.use_time = p->data.use_time + 1; p->data.status = W; }else{ if(p->data.status != F){ printf("[+]process%s Completed\r\n",p->data.p_name); } p->data.status = F; } p = p->next; ad_count = ad_count + 1; if(ad_count%len == 0){ if(continue_flag == FALSE){ printf("[+]All processes are complete!"); break; }else{ continue_flag = FALSE; } printf("\r\n"); } } } int main(){ int process_number = 0; printf("=============================\r\n"); printf("Start creating process block PCB:\r\n"); printf("Please enter the number of processes to be created:"); scanf("%d",&process_number); head = init_process_space(head); struct PCB p; for(int i = 0;i<process_number;i++){ char* pcb_name = itoa((i+1)); long need_time = rand(); //Try to control the time within 10 seconds and shorten the experimental time long use_time = 0; unsigned int status = W; unsigned int priority = RAND_FLAG_OPEN; p = init_pcb(pcb_name,need_time,use_time,status,priority); insert_pcb_space(p); printf("%s\r\n",p.p_name); } rear->next = head->next; //Form a circular queue, and head Data is empty, so point to head - > next printf("=============================\r\n"); disp(head,process_number); //FCFS(head,process_number); // First come first serve algorithm OS_Server(head,process_number); return 0; }