Conception de cours du système d'exploitation basé sur C # WinForm: Simulation de technologie des entrées et de sortie en spoule.
Il est nécessaire de concevoir un processus de sortie de spoulage et deux processus utilisateur qui demandent la sortie, ainsi qu'un programme de service de sortie de spoulage. Lorsque le processus utilisateur demandant la sortie souhaite sortir une série d'informations, le programme de service de sortie est appelé et le programme de service de sortie envoie les informations dans le puits de sortie. Lorsqu'un indicateur de fin de sortie est rencontré, il indique que la sortie du fichier de sortie du processus est terminée. Après cela, un bloc de demande de sortie est appliqué (utilisé pour enregistrer le nom du processus utilisateur demandant la sortie, la position des informations dans le puits de sortie, la longueur de la sortie des informations, etc.) et attendez que le processus de spoulage soit sorti.
Lorsque le processus de sortie de spoulage fonctionne, il sortira réellement vers l'imprimante ou le moniteur en fonction des informations à sortir par chaque processus enregistré dans le bloc de demande. Ici, le processus de sortie SP00ling et le processus utilisateur demandant la sortie peuvent être exécutés simultanément.
La planification du processus utilise un algorithme aléatoire, ce qui est cohérent avec l'aléatoire des informations de sortie du processus. La probabilité de planification des deux processus utilisateur demandant la sortie est de 45% chacune, et le processus de sortie de spoulage est de 10%, ce qui est déterminé par la simulation du nombre aléatoire généré par le générateur de nombres aléatoires.
Il y a trois états de base du processus, à savoir exécutable, en attente et à la fin. L'état exécutable est l'état dans lequel le processus s'exécute ou attend la planification; L'état d'attente est divisé en attente de l'état 1, en attente de l'état 2 et de l'état d'attente 3.
Les conditions de changement d'état sont:
① Lorsque le processus est exécuté, il est défini sur l'état "fin".
② Lorsque le programme de service envoie les informations de sortie au puits de sortie, s'il constate que le puits de sortie est plein, le processus d'appel sera défini sur "Weeting State 1".
③ Lorsque le processus de spoulage est sorti, si la sortie est vide, il entrera "State d'attente 2".
④ Une fois que le processus de spoulage a sorti un bloc d'information, il doit immédiatement libérer l'espace de puits de sortie occupé par le bloc d'informations et définir le processus en attendant la sortie sur "l'état exécutable".
⑤ Une fois que le programme de service a publié des informations au puits de sortie et formé un bloc d'informations de demande de sortie, si le processus de spoulage est dans un état d'attente, il est défini sur "l'état exécutable".
⑥ Lorsque le processus utilisateur demande le bloc de sortie, s'il n'y a pas de bloc de demande disponible, le processus d'appel entre "State 3".
Il existe deux processus utilisateur demandant la sortie dans le système, et les deux processus sont nommés le processus utilisateur A et le processus utilisateur B respectivement. L'utilisateur peut avoir besoin de sortir plusieurs fichiers et les fichiers sont séparés par un indicateur de fin de sortie. L'indicateur d'extrémité de sortie du fichier utilisé dans cette expérience est #.
L'utilisateur doit saisir tous les contenus du fichier pour être sortis pendant la phase d'initialisation, puis l'enregistrer dans un tableau. Lorsque le processus utilisateur est planifié, si les trois conditions suivantes sont remplies: il y a toujours un fichier qui n'est pas sorti, l'espace restant dans le puits de sortie peut baisser le fichier, et il y a un bloc de demande de sortie disponible, le fichier est envoyé au puits de sortie en attente, puis un bloc de demande de sortie est appliqué, et le bloc de demande est ajouté au bloc de demande de la file d'attente, et à l'attente du processus de sortie de débit et de la sortie.
Lorsqu'il s'agit du virage du processus de sortie de spoulage pour occuper le CPU, le processus de sortie de spoulage vérifie d'abord s'il y a des blocs de sortie dans la file d'attente d'attente de blocs de demande, et s'il y a non, il entre dans l'état d'attente. Sinon, la sortie est effectuée, puis l'espace de puits de sortie et le bloc de sortie demandé correspondant sont libérés, et le processus utilisateur qui dort car il n'y a pas de blocs de sortie disponibles.
Le processus de sortie de spoulage et le processus utilisateur peuvent être exécutés simultanément. Cet article résume le processus d'un processus d'exécution (le processus ne se termine pas nécessairement après l'exécution) dans une fonction, chaque fois qu'il génère un nombre aléatoire et exécute un certain processus en fonction du nombre aléatoire. Si le processus est bloqué en raison de certaines situations, le prochain numéro aléatoire sera généré et un autre processus sera planifié. Le processus utilisateur et le processus de sortie de spoulage sont planifiés à leur tour pour diverses raisons, c'est-à-dire une exécution simultanée.
Les fonctions de l'ensemble du système sont divisées en parties suivantes: fonction d'initialisation, fonction de planification, fonction du processus utilisateur et fonction de sortie de spoulage. La fonction d'initialisation est utilisée pour implémenter l'entrée initiale et le stockage des fichiers utilisateur; La fonction de répartition implémente la commutation entre les processus utilisateur et le spoulage des processus de sortie; La fonction de processus utilisateur implémente une série d'actions terminées une fois le processus planifié; La fonction de sortie de spoulage représente l'opération de sortie.
L'organigramme global du fonctionnement du système est illustré à la figure 1:
Le système utilise d'abord la fonction d'initialisation pour initialiser l'entrée de contenu par l'utilisateur, puis génère un nombre aléatoire R entre 0 et 1, et juge si le processus utilisateur doit être exécuté ou si le processus de sortie doit être exécuté en fonction de la taille de R. Une fois le processus utilisateur et le processus de sortie, le programme s'exécute, sinon la planification se poursuivra.
L'utilisateur doit saisir le contenu qu'il souhaite "imprimer". La fonction d'initialisation accepte l'entrée de contenu par l'utilisateur et la coupe en fonction du caractère de fin du fichier, et met le fichier de coupe dans un tableau, et l'envoie bien à la sortie lorsque le processus utilisateur est planifié.
La planification des processus utilise un algorithme aléatoire, et la probabilité de planification des deux processus utilisateur demandant la sortie est de 45% et le processus de sortie de spoulage est de 10%. Cet article utilise des nombres aléatoires pour atteindre cette exigence. Lors de la planification des processus, une décimale entre 0 et 1 est générée au hasard. Si le nombre est inférieur ou égal à 0,45, le processus utilisateur A sera mis en service; Si le nombre est comprise entre 0,45 et 0,9, le processus utilisateur B sera mis en service; Si le nombre est supérieur à 0,9, le processus de sortie de spoulage sera mis en service.
La fonction de processus utilisateur doit d'abord vérifier si le processus actuel répond à trois conditions: le fichier n'est pas sorti, l'espace restant dans le puits de sortie peut baisser le fichier et il existe un bloc de demande de sortie disponible. Si les trois conditions sont remplies, le fichier sera envoyé au puits de sortie et le bloc de demande correspondant est appliqué.
L'organigramme de l'exécution de la fonction du processus utilisateur est illustré à la figure 2:
Lorsque le processus utilisateur s'exécute, s'il est constaté que le fichier a été sorti, le processus s'exécute. Sinon, il est déterminé qu'il y ait un espace restant dans le puits de sortie et aucun état d'attente n'est entré. S'il reste de la place dans la sortie, continuez à juger s'il y a un bloc de sortie. S'il y en a un, envoyez le fichier au puits de sortie et demandez un bloc de sortie et réveillez le processus de sortie potentiellement somnolent, sinon entrez l'état d'attente 3.
La fonction de sortie de spoulage vérifie s'il existe des blocs de demande de sortie, et s'il y a, la sortie et la libération des ressources pertinentes. Sinon, le processus de sortie du spoulage attendra.
L'organigramme de la fonction de sortie de spoulage est illustré à la figure 3:
La définition de PCB est la suivante:
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 ; //用户真实输入的文件个数
}Le processus utilisateur inclut l'ID de numéro de série, l'état du processus, l'état, le contenu à sortir, les indicateurs de sortie de fichier et le nombre de fichiers réels.
Parmi eux, les états du processus possibles dans lesquels le processus utilisateur peuvent exister comprennent: 0 signifie l'état exécutable, 1 signifie que l'état d'attente 1, 3 signifie l'état d'attente 3, 4 signifie fin du processus.
OutputReqBlock est défini comme suit:
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 ;
}
}Le bloc de sortie de demande comprend: l'ID de processus du bloc de demande, la position de départ du fichier dans le puits de sortie, la longueur de la longueur du fichier et le numéro de séquence du fichier à sortir dans tous les fichiers de l'utilisateur.
La définition de Outputwell est la suivante:
class OutputWell {
/*
* 输出井
*/
public char [ ] buffer = new char [ MaxWellLen ] ; //输出缓冲区
public int begin = 0 ; //当前可用位置
public int restSize = MaxWellLen ; //剩余容量
}Les paramètres du puits de sortie sont: le tampon de tampon, utilisé pour stocker les données placées par l'utilisateur; L'emplacement disponible actuel commence, les fichiers sont stockés dans l'ordre dans le puits de sortie et le début pointe toujours vers la position de départ du tampon actuellement disponible; La capacité restante reposait, la capacité restante dans le tampon, initialement la longueur du tampon Maxwelllen.
L'utilisateur entre dans les informations pour «imprimer» dans la zone de texte, puis sélectionne le processus que le contenu de sortie appartient (A ou B). Enfin, cliquez sur le bouton d'initialisation pour démarrer la fonction d'initialisation. La fonction d'initialisation utilise d'abord un objet String pour stocker l'entrée de contenu par l'utilisateur. Ensuite, vérifiez si le contenu entré par l'utilisateur se termine par un numéro # et invitez l'utilisateur à rentrer s'il n'est pas légal. Une fois l'entrée légale, le contenu entré par l'utilisateur est coupé en fonction du numéro # et la chaîne est coupée en plusieurs chaînes. Enfin, un objet PCB est initialisé à l'aide des informations générées et placée dans la file d'attente d'attente Waitqueue.
Étant donné que l'utilisateur peut cliquer plusieurs fois sur le bouton d'initialisation, il est nécessaire de déterminer si le processus actuel a été initialisé avant chaque clic. Si l'utilisateur a déjà terminé l'initialisation mais a cliqué à nouveau sur le bouton d'initialisation, le contenu d'origine sera écrasé.
Le puits de sortie est automatiquement initialisé lorsque l'interface système est chargée.
Le code de fonction d'initialisation est ignoré!
Afin d'atteindre le hasard, chaque fois que vous souhaitez planifier, un nombre aléatoire entre 0 et 1 est généré en utilisant la fonction aléatoire de C #. Si le nombre aléatoire est inférieur ou égal à 0,45 signifie que le processus utilisateur A sera prévu ensuite; Si le nombre aléatoire se situe entre 0,45 et 0,9 signifie que le processus utilisateur B sera planifié ensuite; Si le nombre aléatoire est supérieur à 0,9 signifie que le processus de sortie de spoulage sera programmé ensuite.
La mise en œuvre de la fonction Scheduler est la suivante:
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输出进程
}
} Utilisé pour implémenter une série d'opérations effectuées lorsque le processus utilisateur est en cours d'exécution.
Lorsque le processus utilisateur est planifié, vérifiez d'abord s'il y a encore des fichiers qui n'ont pas été bien envoyés à la sortie. S'il n'y a pas, le processus utilisateur actuel est défini sur l'état final et la fonction renvoie.
Le processus utilisateur n'a pas encore pris fin, ce qui signifie qu'il y a encore des fichiers qui n'ont pas été bien envoyés à la sortie. Boucle pour trouver un bloc de fichiers qui n'a pas été sorti (l'indicateur correspondant est 1), puis demandez si l'espace restant dans le puits de sortie peut toujours placer ce bloc de fichiers. Sinon, définissez l'état de processus pour attendre l'état 1 et la fonction renvoie. S'il reste de la place, vérifiez s'il existe toujours le bloc de sortie de demande disponible. Si le processus n'est pas défini pour attendre l'état 3, la fonction renvoie. Sinon, le bloc de fichiers est envoyé au puits de sortie et les paramètres pertinents du puits de sortie sont modifiés. Ensuite, un bloc de sortie de demande est appliqué à la file d'attente de sortie PrintQueue, et la sortie d'impression est imprimée lorsque le processus de sortie de spoulage est planifié. Enfin, si le processus de sortie de spoulage est dans un état d'attente, le processus utilisateur doit le réveiller.
Diverses situations pendant l'exécution de la fonction de processus utilisateur sont enregistrées via une liste pour l'affichage final de résultat. La liste comprend: le numéro de séquence de planification actuel, le numéro de processus, l'état du processus, l'état du puits de sortie, le nombre de blocs de demande disponible, le numéro de séquence de fichiers et la longueur du fichier.
Le code de fonction du processus utilisateur est ignoré!
La fonction de la fonction de sortie consiste à sélectionner un bloc de sortie de demande, puis à diffuser le contenu dedans et enfin à libérer la ressource correspondante.
Vérifiez d'abord si le puits de sortie est vide. Si le processus de sortie vide est défini pour attendre l'état 2, la fonction renvoie. Sinon, vérifiez s'il existe des blocs de sortie de demande dans la file d'attente de sortie de demande qui doivent être sortis, et aucune fonction ne renvoie. Sinon, le bloc de sortie de la demande à la tête de la file d'attente est récupéré à partir de la file d'attente de sortie de demande, puis le bloc de demande est sorti, et l'espace de puits de sortie et le bloc de demande de sortie correspondant sont libérés.
Lors de la sortie de la fonction de sortie, le contenu de sortie doit être affiché dans la zone de sortie du fichier.
Le code de fonction de sortie est ignoré!
L'utilisateur clique sur le bouton "Exécuter le programme" et commence à exécuter la fonction principale. Le processus en cours est ajusté dynamiquement en fonction de la situation actuelle.
La fonction principale détermine d'abord si les deux processus utilisateur ont été initialisés et ne peuvent être exécutés qu'après l'initialisation, sinon une erreur sera signalée.
Après initialisation, cliquez à nouveau sur le bouton "Exécuter". Tant qu'il y a un processus qui n'est pas à l'état final, ou qu'un bloc de demande n'a pas été sorti, continuez à planifier. Lors de la planification, vous devez déterminer si le processus actuel est terminé et sortir l'état pertinent une fois terminé.
Le code de fonction principal est ignoré!
La description de divers paramètres utilisés dans l'expérience est présentée dans le tableau 1:
| Nom du paramètre | Maxwelllen | Maxfilecount | blocage de blocage |
|---|---|---|---|
| Description du paramètre | Longueur de sortie | Le nombre maximum de fichiers qu'un utilisateur peut sortir | Nombre de blocs demandés |
| Valeur du paramètre | 15 | 10 | 3 |
L'interface système est illustrée à la figure 4:
L'interface système est divisée en trois sections: initialisation, processus de planification et zone de sortie de fichier. La section d'initialisation contient une zone de texte, une boîte de sélection et un bouton. L'utilisateur entre dans le fichier à imprimer dans la zone de texte, puis l'initialise. La section de processus de planification est principalement un tableau qui affiche le processus détaillé de planification de processus. La section de sortie du fichier est utilisée pour afficher le processus d'impression de tous les fichiers.
L'utilisateur sélectionne d'abord un processus, la valeur par défaut initiale est A, puis met le fichier à sortir dans la zone de texte de la section d'initialisation, puis clique sur le bouton d'initialisation. L'initialisation est réussie, comme le montre la figure 5:
Pour le processus B, effectuez les opérations ci-dessus comme le montre la figure 6:
Une fois l'initialisation des deux processus utilisateur terminée, cliquez sur le bouton Exécuter le programme et les résultats sont présentés sur la figure 7 et la figure 8:
Ce qui suit est une brève analyse du contenu de la figure 7. Comme le montre la figure 9:
Le processus de sortie a été planifié pour la première fois, car la sortie est vide pour le moment, donc l'état du processus de sortie est en attente de l'état 2, et le nombre de blocs de demande disponible est 3. La deuxième fois que le processus A est planifié. L'état du processus A est exécutable. Le nombre de blocs de demande disponibles est 3. A envoie le fichier 0 au puits de sortie. La longueur du fichier 0 ("ABCD") est 4. Le processus de sortie est planifié pour la troisième fois. L'espace disponible du puits de sortie est de 15-4 = 11, le nombre de blocs de demande disponibles devient 2 et le fichier 0 du processus A est la sortie, comme indiqué dans la zone de sortie du fichier, et l'espace pertinent est libéré.