Operating system course design based on C# winform: SPOOLING spooled input and output technology simulation.
It is required to design a SPOOLING output process and two user processes that request output, as well as a SPOOLING output service program. When the user process requesting output wishes to output a series of information, the output service program is called, and the output service program sends the information into the output well. When an output end flag is encountered, it indicates that the output file output of the process is completed. After that, an output request block is applied (used to record the name of the user process requesting output, the position of the information in the output well, the length of the information to be output, etc.), and wait for the SPOOLING process to output.
When the SPOOLING output process is working, it will actually output to the printer or monitor based on the information to be output by each process recorded in the request block. Here, the SP00LING output process and the user process requesting output can be run concurrently.
Process scheduling uses a random algorithm, which is consistent with the randomness of the process's output information. The scheduling probability of the two user processes requesting output is 45% each, and the SPOOLING output process is 10%, which is determined by the simulation of the random number generated by the random number generator.
There are three basic states of the process, namely executable, waiting and end. The executable state is the state in which the process is running or waiting for scheduling; the waiting state is divided into waiting state 1, waiting state 2 and waiting state 3.
The conditions for state change are:
① When the process is executed, it is set to the "end" state.
② When the service program sends the output information to the output well, if it finds that the output well is full, the calling process will be set to "Waiting State 1".
③ When the SPOOLING process is output, if the output is empty, it will enter "waiting state 2".
④ After the SPOOLING process outputs an information block, it should immediately release the output well space occupied by the information block and set the process waiting for output to the "executable state".
⑤ After the service program outputs information to the output well and forms an output request information block, if the SPOOLING process is in a waiting state, it is set to the "executable state".
⑥ When the user process requests the output block, if there is no request block available, the calling process enters "Waiting State 3".
There are two user processes requesting output in the system, and the two processes are named User Process A and User Process B respectively. The user may need to output more than one file, and the files are separated by an output end flag. The file output end flag used in this experiment is #.
The user needs to enter all the file contents to be output during the initialization phase and then save it into an array. When the user process is scheduled, if the following three conditions are met: there is still a file that is not outputted, the remaining space in the output well can put the file down, and there is an available output request block, the file is sent to the output well, and then an output request block is applied for, and the request block is added to the request block waiting queue, and waiting for the SPOOLING output process to schedule and output.
When it is the SPOOLING output process's turn to occupy the CPU, the SPOOLING output process first checks whether there are output blocks in the request block waiting queue to output, and if there is no, it enters the waiting state. Otherwise, output is performed, and then the output well space and the corresponding requested output block are released, and the user process that is sleeping because there are no available output blocks.
The SPOOLING output process and the user process can be executed concurrently. This article abstracts the process of one execution process (the process does not necessarily end after execution) into a function, each time it generates a random number and executes a certain process according to the random number. If the process is blocked due to certain situations, the next random number will be generated and another process will be scheduled. The user process and the SPOOLING output process are scheduled in turn for various reasons, that is, concurrent execution.
The functions of the entire system are divided into the following parts: initialization function, schedule function, user process function, and SPOOLING output function. The initialization function is used to implement the initial input and storage of user files; the dispatch function implements switching between user processes and SPOOLING output processes; the user process function implements a series of actions completed after the process is scheduled; the SPOOLING output function represents the output operation.
The overall flowchart of the system operation is shown in Figure 1:
The system first uses the initialization function to initialize the content input by the user, and then generates a random number R between 0 and 1, and judges whether the user process should be executed or the output process should be executed according to the size of R. After the user process and output process are executed, the program runs over, otherwise the scheduling will continue.
The user needs to enter the content he wants to "print". The initialization function accepts the content input by the user and cuts it according to the file ending character, and puts the cut file into an array, and sends it to the output well when the user process is scheduled.
Process scheduling uses a random algorithm, and the scheduling probability of the two user processes requesting output is 45%, and the SPOOLING output process is 10%. This paper uses random numbers to achieve this requirement. When performing process scheduling, a decimal between 0 and 1 is randomly generated. If the number is less than or equal to 0.45, user process A will be put into operation; if the number is between 0.45 and 0.9, user process B will be put into operation; if the number is greater than 0.9, SPOOLING output process will be put into operation.
The user process function first needs to check whether the current process meets three conditions: the file is not output, the remaining space in the output well can put the file down, and there is an available output request block. If the three conditions are met, the file will be sent to the output well and the corresponding request block is applied for.
The flowchart of user process function execution is shown in Figure 2:
When the user process executes, if it is found that the file has been output, the process runs end. Otherwise, it is determined whether there is any remaining space in the output well and no waiting state is entered. If there is room left in the output well, continue to judge whether there is an output block. If there is one, send the file to the output well and request an output block, and wake up the potentially sleepy output process, otherwise enter wait state 3.
The SPOOLING output function checks whether there are output request blocks, and if there is, output and release relevant resources. Otherwise, the SPOOLING output process will wait.
The flowchart of the SPOOLING output function is shown in Figure 3:
The definition of PCB is as follows:
class PCB {
/*
* 进程描述
*/
public int id ; //序号
public int status ; //状态,0表示可执行,123表示三个等待状态,4表示结束
public string [ ] contents = new string [ MaxFileCount ] ; //要输出的内容
public int [ ] flags = new int [ MaxFileCount ] ; //为1表示该文件已经被输出,初始全部为0
public int fileCount ; //用户真实输入的文件个数
}The user process includes the serial number id, process status status, content to be output, file output flags, and real file count.
Among them, the possible process states in which the user process may exist include: 0 means executable state, 1 means waiting state 1, 3 means waiting state 3, 4 means ending of the process.
OutPutReqBlock is defined as follows:
class OutputReqBlock {
/*
* 输出请求块
*/
public int id ; //要求进行输出的进程的id
public int start ; //文件在输出井中的起始位置
public int length ; //文件长度
public int fileIndex ; //要输出文件的序号
public OutputReqBlock ( int id , int start , int length , int fileIndex ) {
this . id = id ;
this . start = start ;
this . length = length ;
this . fileIndex = fileIndex ;
}
}The request output block includes: the process id of the request block, the starting position of the file in the output well, the length of the file length, and the sequence number of the file to be output in all the user's files.
The definition of OutputWell is as follows:
class OutputWell {
/*
* 输出井
*/
public char [ ] buffer = new char [ MaxWellLen ] ; //输出缓冲区
public int begin = 0 ; //当前可用位置
public int restSize = MaxWellLen ; //剩余容量
}The parameters of the output well are: buffer buffer, used to store data placed by the user; the current available location begin, the files are stored in order in the output well, and the beginning always points to the starting position of the currently available buffer; the remaining capacity restSize, the remaining capacity in the buffer, initially the buffer length MaxWellLen.
The user enters the information to "print" in the text box, then selects which process the output content belongs to (A or B). Finally, click the initialization button to start the initialization function. The initialization function first uses a string object to store the content input by the user. Then, check whether the content entered by the user ends with a # number, and prompt the user to re-enter if it is not legal. After the input is legal, the content entered by the user is cut according to the # number, and the string is cut into multiple strings. Finally, a PCB object is initialized using the generated information and placed in the waiting queue waitQueue.
Since the user may click the initialization button multiple times, it is necessary to determine whether the current process has been initialized before each click. If the user has already completed initialization but clicked the initialization button again, the original content will be overwritten.
The output well is automatically initialized when the system interface is loaded.
Initialization function code is skipped!
In order to achieve randomness, each time you want to schedule, a random number between 0 and 1 is generated using C#'s Random function. If the random number is less than or equal to 0.45 means that the user process A will be scheduled next; if the random number is between 0.45 and 0.9 means that the user process B will be scheduled next; if the random number is greater than 0.9 means that the SPOOLING output process will be scheduled next.
The implementation of the scheduler function is as follows:
private int dispatch ( ) {
/*
* 进程调度
*/
double res = rd . NextDouble ( ) ; //产生一个01之间的小数
if ( res <= 0.45 ) {
return 0 ;
} else if ( res <= 0.9 ) {
return 1 ;
} else {
return 2 ; //012分别表示两个进程和SPOOLing输出进程
}
} Used to implement a series of operations performed when the user process is running.
When the user process is scheduled, first check whether there are still files that have not been sent to the output well. If there is no, the current user process is set to the end state and the function returns.
The user process has not yet ended, which means that there are still files that have not been sent to the output well. Loop to find a file block that has not been output (the corresponding flag is 1), and then query whether the remaining space in the output well can still put this file block. If not, set the process state to wait state 1 and the function returns. If there is still room left, then check whether there is still available request output block. If the process is not set to wait state 3, the function returns. Otherwise, the file block is sent to the output well and the relevant parameters of the output well are modified. Then, a request output block is applied to the output queue printQueue, and the print output is printed when the SPOOLING output process is scheduled. Finally, if the SPOOLING output process is in a waiting state, the user process needs to wake it up.
Various situations during the user process function run are saved through a list for the final result display. The list includes: the current scheduling sequence number, process number, process status, output well status, number of available request blocks, file sequence number, and file length.
User process function code is skipped!
The function of the output function is to select a request output block, then output the contents in it, and finally release the corresponding resource.
First check whether the output well is empty. If the empty output process is set to wait state 2, the function returns. Otherwise, check whether there are request output blocks in the request output queue that need to be output, and no function returns. Otherwise, the request output block at the head of the queue is fetched from the request output queue, and then the request block is output, and the corresponding output well space and request block are freed.
When outputting the output function, the output content must be displayed to the file output area.
Output function code is skipped!
The user clicks the "Program Run" button and starts running the main function. The running process is dynamically adjusted according to the current situation.
The main function first determines whether both user processes have been initialized and can only be run after initialization, otherwise an error will be reported.
After initialization, click the "Program Run" button again. As long as there is a process that is not in the end state, or a request block has not been output, continue to schedule. When scheduling, you must determine whether the current process has ended, and output the relevant state when it is finished.
The main function code is skipped!
The description of various parameters used in the experiment is shown in Table 1:
| Parameter name | MaxWellLen | MaxFileCount | blockCount |
|---|---|---|---|
| Parameter description | Output well length | The maximum number of files a user can output | Number of requested blocks |
| Parameter value | 15 | 10 | 3 |
The system interface is shown in Figure 4:
The system interface is divided into three sections: initialization, scheduling process and file output area. The initialization section contains a text box, a selection box, and a button. The user enters the file to be printed in the text box and then initializes it. The scheduling process section is mainly a table that displays the detailed process of process scheduling. The file output section is used to display the printing process of all files.
The user first selects a process, the initial default is A, and then puts the file to be output into the text box of the initialization section, and then clicks the initialization button. The initialization is successful, as shown in Figure 5:
For process B, perform the above operations as shown in Figure 6:
After the initialization of the two user processes is completed, click the program run button, and the results are shown in Figure 7 and Figure 8:
The following is a brief analysis of the contents of Figure 7. As shown in Figure 9:
The output process was scheduled for the first time, because the output is empty at this time, so the output process state is waiting state 2, and the number of available request blocks is 3. The second time schedules process A. The state of process A is executable. The number of available request blocks is 3. A sends file 0 to the output well. The length of file 0 ("abcd") is 4. The output process is scheduled for the third time. The available space of the output well is 15-4=11, the number of available request blocks becomes 2, and the file 0 of process A is output, as shown in the file output area, and the relevant space is released.