C#Winformに基づくオペレーティングシステムコース設計:スプールスプール入力および出力テクノロジーシミュレーション。
スプール出力プロセスと、出力を要求する2つのユーザープロセス、およびスプール出力サービスプログラムを設計する必要があります。出力を要求するユーザープロセスが一連の情報を出力したい場合、出力サービスプログラムが呼び出され、出力サービスプログラムは情報を出力にウェルに送信します。出力エンドフラグに遭遇すると、プロセスの出力ファイル出力が完了したことを示します。その後、出力要求ブロックが適用され(出力を要求するユーザープロセスの名前、出力の情報の位置、出力の長さなど)、スプールプロセスが出力まで待機します。
スプール出力プロセスが機能している場合、リクエストブロックに記録された各プロセスによって出力される情報に基づいて、実際にプリンターまたはモニターに出力されます。ここでは、出力を要求するSP00LING出力プロセスとユーザープロセスを同時に実行できます。
プロセススケジューリングは、プロセスの出力情報のランダム性と一致するランダムアルゴリズムを使用します。出力を要求する2つのユーザープロセスのスケジューリング確率はそれぞれ45%であり、スプール出力プロセスは10%であり、これは乱数ジェネレーターによって生成される乱数のシミュレーションによって決定されます。
プロセスには3つの基本的な状態があります。つまり、実行可能、待機、終了です。実行可能な状態は、プロセスが実行またはスケジューリングを待っている状態です。待機状態は、待機状態1、待機状態2、待機状態3に分かれています。
州の変化の条件は次のとおりです。
processプロセスが実行されると、「終了」状態に設定されます。
serviceサービスプログラムが出力情報を出力にウェルに送信すると、出力が井戸がいっぱいであることがわかった場合、呼び出しプロセスは「待機状態1」に設定されます。
spoolingプロセスが出力の場合、出力が空の場合、「待機状態2」に入ります。
spoolingプロセスが情報ブロックを出力した後、情報ブロックが占める出力ウェルスペースを直ちに放出し、出力を「実行可能状態」に待つプロセスを設定する必要があります。
serviceサービスプログラムが情報を出力し、出力要求情報ブロックを形成した後、スプールプロセスが待機状態にある場合、「実行可能状態」に設定されます。
userユーザープロセスが出力ブロックを要求した場合、リクエストブロックが利用できない場合、呼び出しプロセスは「待機状態3」に入ります。
システムに出力を要求する2つのユーザープロセスがあり、2つのプロセスはそれぞれユーザープロセスAとユーザープロセスBという名前です。ユーザーは複数のファイルを出力する必要があり、ファイルは出力エンドフラグによって分離されます。この実験で使用されるファイル出力エンドフラグは#です。
ユーザーは、初期化フェーズ中に出力するためにすべてのファイルコンテンツを入力して、配列に保存する必要があります。ユーザープロセスがスケジュールされると、次の3つの条件が満たされている場合:まだ出力されていないファイルがあり、出力の残りのスペースがファイルを下げることができ、利用可能な出力要求ブロックがあり、ファイルが出力に送信され、出力要求ブロックが適用され、リクエストブロックがリクエストブロックを待機し、出力をスケジュートします。
CPUを占有するスプール出力プロセスのターンである場合、スプール出力プロセスは、最初にリクエストブロックに出力ブロックが出力を待機しているかどうかをチェックします。それ以外の場合、出力が実行され、その後、出力ウェルスペースと対応する要求された出力ブロックがリリースされ、利用可能な出力ブロックがないため睡眠中のユーザープロセスがリリースされます。
スプール出力プロセスとユーザープロセスを同時に実行できます。この記事では、1つの実行プロセスのプロセス(プロセスは必ずしも実行後に終了するとは限らない)を関数に抽象化します。たびに、乱数を生成し、乱数に応じて特定のプロセスを実行します。特定の状況のためにプロセスがブロックされている場合、次の乱数が生成され、別のプロセスがスケジュールされます。ユーザープロセスとスプール出力プロセスは、さまざまな理由、つまり同時実行のために順番にスケジュールされます。
システム全体の関数は、初期化関数、スケジュール関数、ユーザープロセス関数、スプール出力関数の次の部分に分割されます。初期化関数は、ユーザーファイルの初期入力とストレージを実装するために使用されます。ディスパッチ関数は、ユーザープロセス間の切り替えとスプール出力プロセスを実装します。ユーザープロセス関数は、プロセスがスケジュールされた後に完了した一連のアクションを実装します。スプール出力関数は、出力操作を表します。
システム操作の全体的なフローチャートを図1に示します。
システムは最初に初期化関数を使用してユーザーによるコンテンツ入力を初期化し、次に0〜1の間の乱数Rを生成し、ユーザープロセスを実行するか、出力プロセスを実行するか、ユーザープロセスと出力プロセスが実行された後、プログラムが実行され、そうでなければスケジュールが続きます。
ユーザーは、「印刷」したいコンテンツを入力する必要があります。初期化関数は、ユーザーによるコンテンツ入力を受け入れ、ファイルの終了文字に従ってカットし、カットファイルを配列に配置し、ユーザープロセスがスケジュールされたときに出力に適切に送信します。
プロセススケジューリングはランダムアルゴリズムを使用し、出力を要求する2つのユーザープロセスのスケジューリング確率は45%で、スプール出力プロセスは10%です。このペーパーでは、この要件を達成するために乱数を使用しています。プロセススケジューリングを実行すると、0〜1の小数がランダムに生成されます。数値が0.45以下の場合、ユーザープロセスAが操作されます。数値が0.45〜0.9の場合、ユーザープロセスBが操作されます。数値が0.9を超える場合、スプール出力プロセスが操作されます。
ユーザープロセス関数は、最初に現在のプロセスが3つの条件を満たしているかどうかを確認する必要があります。ファイルは出力ではなく、出力ウェルの残りのスペースがファイルを下に置き、利用可能な出力要求ブロックがあります。 3つの条件が満たされている場合、ファイルは出力にウェルに送信され、対応するリクエストブロックが適用されます。
ユーザープロセス機能の実行のフローチャートを図2に示します。
ユーザープロセスが実行されると、ファイルが出力されていることが判明した場合、プロセスは終了します。それ以外の場合、出力に残りのスペースがあるかどうかが判断され、待機状態が入力されていません。出力に十分な部屋が残っている場合は、出力ブロックがあるかどうかを判断し続けます。ある場合は、ファイルを出力に適切に送信し、出力ブロックをリクエストし、潜在的に眠い出力プロセスを目覚めさせます。
スプール出力関数は、出力要求ブロックがあるかどうか、および出力があるかどうかをチェックし、関連するリソースをリリースします。それ以外の場合、スプール出力プロセスが待機します。
スプール出力関数のフローチャートを図3に示します。
PCBの定義は次のとおりです。
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 ; //用户真实输入的文件个数
}ユーザープロセスには、シリアル番号ID、プロセスステータスのステータス、出力になるコンテンツ、ファイル出力フラグ、および実際のファイルカウントが含まれます。
その中で、ユーザープロセスが存在する可能性のあるプロセス状態には次のものが含まれます。
outputreqblockは次のように定義されています。
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 ;
}
}リクエスト出力ブロックには、リクエストブロックのプロセスID、出力のファイルの開始位置、ファイルの長さの長さ、およびすべてのユーザーのファイルで出力されるファイルのシーケンス番号が含まれます。
outputwellの定義は次のとおりです。
class OutputWell {
/*
* 输出井
*/
public char [ ] buffer = new char [ MaxWellLen ] ; //输出缓冲区
public int begin = 0 ; //当前可用位置
public int restSize = MaxWellLen ; //剩余容量
}出力のパラメーターは次のとおりです。ユーザーが配置したデータを保存するために使用されるバッファバッファー。現在の利用可能な場所が始まり、ファイルは出力の順番に順番に保存され、最初は現在利用可能なバッファーの開始位置を常に指します。残りの容量は、バッファ内の残りの容量、最初はバッファー長maxwelllenです。
ユーザーは情報を入力してテキストボックスに「印刷」してから、出力コンテンツが(aまたはb)に属するプロセスを選択します。最後に、[初期化]ボタンをクリックして、初期化関数を開始します。初期化関数は、最初に文字列オブジェクトを使用して、ユーザーによるコンテンツ入力を保存します。次に、ユーザーが入力したコンテンツが#番号で終了するかどうかを確認し、合法でない場合はユーザーに再入力するように促します。入力が合法であると、ユーザーが入力したコンテンツは#番号に従ってカットされ、文字列は複数の文字列にカットされます。最後に、生成された情報を使用してPCBオブジェクトが初期化され、待機キューウェイトに配置されます。
ユーザーは初期化ボタンを複数回クリックする可能性があるため、クリックする前に現在のプロセスが初期化されているかどうかを判断する必要があります。ユーザーがすでに初期化を完了しているが、初期化ボタンを再度クリックした場合、元のコンテンツが上書きされます。
システムインターフェイスがロードされると、出力ウェルが自動的に初期化されます。
初期化関数コードがスキップされます!
ランダム性を達成するために、スケジュールするたびに、C#のランダム関数を使用して0〜1のランダム数が生成されます。乱数が0.45以下の場合、ユーザープロセスAが次にスケジュールされることを意味します。乱数が0.45〜0.9の間である場合、ユーザープロセスBが次にスケジュールされることを意味します。乱数が0.9を超える場合、スプール出力プロセスが次にスケジュールされることを意味します。
スケジューラ関数の実装は次のとおりです。
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输出进程
}
} ユーザープロセスが実行されているときに実行される一連の操作を実装するために使用されます。
ユーザープロセスがスケジュールされている場合は、最初に出力に送信されていないファイルがまだ適切にあるかどうかを確認します。 noがある場合、現在のユーザープロセスが終了状態に設定され、関数が返されます。
ユーザープロセスはまだ終了していません。つまり、出力に適切に送信されていないファイルがまだあります。ループ出力(対応するフラグは1)になっていないファイルブロックを見つけ、出力ウェルの残りのスペースがこのファイルブロックを配置できるかどうかを照会します。そうでない場合は、プロセス状態を状態1を待機するように設定し、関数が戻ります。まだ部屋が残っている場合は、まだ利用可能なリクエスト出力ブロックがあるかどうかを確認してください。プロセスが状態3を待機するように設定されていない場合、関数は戻ります。それ以外の場合、ファイルブロックは出力にウェルに送信され、出力ウェルの関連パラメーターが変更されます。次に、リクエスト出力ブロックが出力キューPrintqueueに適用され、スプール出力プロセスがスケジュールされているときに印刷出力が印刷されます。最後に、スプール出力プロセスが待機状態にある場合、ユーザープロセスはそれを起こす必要があります。
ユーザープロセス関数の実行中のさまざまな状況は、最終結果表示のリストに保存されます。リストには、現在のスケジューリングシーケンス番号、プロセス番号、プロセスステータス、出力ウェルステータス、利用可能な要求ブロックの数、ファイルシーケンス番号、ファイルの長さが含まれます。
ユーザープロセス機能コードがスキップされます!
出力関数の関数は、リクエスト出力ブロックを選択してから、内容を出力し、最後に対応するリソースをリリースすることです。
最初に、出力井戸が空であるかどうかを確認します。空の出力プロセスが状態2を待機するように設定されている場合、関数は戻ります。それ以外の場合は、リクエスト出力キューに出力が必要なリクエスト出力ブロックがあるかどうかを確認し、機能が返されません。それ以外の場合、キューのヘッドにあるリクエスト出力ブロックがリクエスト出力キューからフェッチされ、リクエストブロックが出力され、対応する出力ウェルスペースとリクエストブロックが解放されます。
出力関数を出力するときは、出力コンテンツをファイル出力領域に表示する必要があります。
出力関数コードがスキップされます!
ユーザーは「プログラム実行」ボタンをクリックし、メイン関数の実行を開始します。実行プロセスは、現在の状況に応じて動的に調整されます。
メイン関数は、最初に両方のユーザープロセスが初期化され、初期化後にのみ実行できるかどうかを決定します。そうしないと、エラーが報告されます。
初期化後、[プログラム実行]ボタンをもう一度クリックします。終了状態にないプロセスがあるか、リクエストブロックが出力されていない限り、引き続きスケジュールを立てます。スケジューリングの場合、現在のプロセスが終了したかどうかを判断し、関連状態が終了したときに出力する必要があります。
メイン関数コードがスキップされています!
実験で使用されているさまざまなパラメーターの説明を表1に示します。
| パラメーター名 | マックスウェルレン | MaxFileCount | ブロックカウント |
|---|---|---|---|
| パラメーターの説明 | 井戸の出力長 | ユーザーが出力できるファイルの最大数 | 要求されたブロックの数 |
| パラメーター値 | 15 | 10 | 3 |
システムインターフェイスを図4に示します。
システムインターフェイスは、初期化、スケジューリングプロセス、ファイル出力領域の3つのセクションに分割されます。初期化セクションには、テキストボックス、選択ボックス、ボタンが含まれています。ユーザーはファイルをインタートしてテキストボックスに印刷してから初期化します。スケジューリングプロセスセクションは、主にプロセススケジューリングの詳細なプロセスを表示するテーブルです。ファイル出力セクションは、すべてのファイルの印刷プロセスを表示するために使用されます。
ユーザーは最初にプロセスを選択します。最初のデフォルトはaです。次に、ファイルを初期化セクションのテキストボックスに出力するようにし、[初期化]ボタンをクリックします。図5に示すように、初期化は成功しています。
プロセスBの場合、図6に示すように上記の操作を実行します。
2つのユーザープロセスの初期化が完了したら、[プログラム]ボタンをクリックすると、結果を図7と図8に示します。
以下は、図9に示すように、図7の内容の簡単な分析です。
出力プロセスは初めてスケジュールされました。これは、出力が現時点では空であるため、出力プロセス状態は待機状態2で、利用可能な要求ブロックの数は3です。プロセスAの状態は実行可能です。利用可能な要求ブロックの数は3です。Aはファイル0を出力に送信します。ファイル0( "ABCD")の長さは4です。出力プロセスは3回目にスケジュールされます。出力ウェルの使用可能なスペースは15-4 = 11、使用可能な要求ブロックの数が2になり、プロセスAのファイル0がファイル出力領域に示されているように出力され、関連するスペースがリリースされます。