1. 先着順のスケジューリング アルゴリズム
(1) アルゴリズムの内容:先着順スケジューリング アルゴリズムは、最も単純なスケジューリング アルゴリズムであり、上位スケジューリングと下位スケジューリングの両方に適用できます。高度なスケジューリングでは、FCFS スケジューリング アルゴリズムは、バックアップ ジョブ キューに入る順序に従って、メモリに入るジョブを選択します。つまり、最初にバックアップ ジョブ キューに入るジョブが、最初にメモリに入るジョブとして選択され、その後、ジョブが作成されます。選択したジョブのプロセスを選択し、ジョブに必要なリソースを割り当てます。低レベルのスケジューリングでは、FCFS スケジューリング アルゴリズムが毎回メモリ プロセス/スレッド準備完了キューから最初にエントリするプロセス/スレッドを選択し、プロセス/スレッド スケジューラがそれに CPU を割り当てて実行します。
(2) アルゴリズム要件:各プロセスはプロセス制御ブロック (PCB) によって表されます。プロセス制御ブロックには、プロセス名、到着時間、実行時間、開始時間、完了時間、待機時間、ターンアラウンド時間、委任ターンアラウンド時間などの情報を含めることができます。最初に準備完了キューに入ったプロセスには、最初に実行するプロセッサが割り当てられます。プロセスがプロセッサを占有すると、プロセスが作業を終了するか、プロセッサを解放する前にイベントの発生を待っているために実行を続行できなくなるまで実行を続けます。
(3) 設計思想:アルゴリズムはプロセスの到着時間順に実行され、先に到着したものから実行されます。
(4) アルゴリズム分析:最初に PCB 構造を定義します。
input() 入力関数を定義し、プロセス番号、到着時間、実行時間を入力します。
各プロセス ブロックのさまざまな時間を出力するために、output() 出力関数を定義します。
Rank() ソート関数を定義して、到着時間に従ってプロセスをソートします。
さまざまな時間を計算するFCFS ()先着順アルゴリズム関数を定義します。
main() メイン関数を定義して、先着順関数を実現します。
(5) コアコード:
#include<stdio.h>
double atime; //平均周转时间
double awtime; //平均带权周转时间
struct PCB //声明结构体类型PCB
{
char name[20]; //进程号
int arrivaltime; //到达时间
int runtime; //运行时间
int starttime; //开始时间
int finishtime; //完成时间
int waitingtime; //等待时间
int cycletime; //周转时间
double wctime; //带权周转时间
};
struct PCB pcb[100];
/*输入函数*/
int input(int n)
{
printf("请依次输入进程号、到达时间、运行时间:\n");
for(int i=0;i<n;i++)
{
scanf("%s\t%d\t%d",pcb[i].name,&pcb[i].arrivaltime,&pcb[i].runtime);
}
}
/*输出函数*/
int output(int n)
{
printf("\n======================================================================================================================\n");
printf("进程号 \t到达时间\t运行时间\t开始时间\t完成时间\t等待时间\t周转时间\t带权周转时间\n");
printf("----------------------------------------------------------------------------------------------------------------------\n");
for(int i=0;i<n;i++)
{
printf("%3s\t %d\t\t %d\t\t %d\t\t %d\t\t %d\t\t %d\t\t %.2lf\n",pcb[i].name,pcb[i].arrivaltime,pcb[i].runtime,pcb[i].starttime,pcb[i].finishtime,pcb[i].waitingtime,pcb[i].cycletime,pcb[i].wctime);
}
printf("----------------------------------------------------------------------------------------------------------------------\n");
printf("\t平均周转时间 \t\t%.2lf\t\n",atime);
printf("----------------------------------------------------------------------------------------------------------------------\n");
printf("\t平均带权周转时间\t\t%.2lf\t\n",awtime);
printf("======================================================================================================================\n");
}
/*按到达时间进行排序*/
int rank(int n)
{
struct PCB t;
for(int j=0;j<n-1;j++) //冒泡法排序
for(int i=0;i<n-1-j;i++)
{
if(pcb[i].arrivaltime>pcb[i+1].arrivaltime)
{
t=pcb[i];
pcb[i]=pcb[i+1];
pcb[i+1]=t;
}
}
}
/*先来先服务算法*/
int FCFS(int n)
{
/*完成时间*/
if(pcb[0].arrivaltime!=0) //第一个进程到达时间不为0时,其完成时间=开始时间+运行时间
{
pcb[0].finishtime=pcb[0].starttime+pcb[0].runtime;
}
else
pcb[0].finishtime=pcb[0].runtime; //第一个进程到达时间为0时,其完成时间=运行时间
for(int i=1;i<n;i++)
{
if(pcb[i-1].finishtime>=pcb[i].arrivaltime) //如果前一个进程的完成时间大于等于当前进程的到达时间
{
pcb[i].finishtime=pcb[i-1].finishtime+pcb[i].runtime; //当前进程的完成时间=前一个进程的完成时间+该进程的运行时间
}
else
{
pcb[i].finishtime=pcb[i].arrivaltime+pcb[i].runtime; //否则为当前进程的到达时间+运行时间
}
}
/*开始时间*/
pcb[0].starttime=pcb[0].arrivaltime; //第一个进程的开始时间即到达时间
for(int i=1;i<n;i++)
{
pcb[i].starttime=pcb[i-1].finishtime; //从第二个进程开始,开始时间=前一个进程的完成时间
}
/*等待时间 周转时间 带权周转时间*/
for(int i=0;i<n;i++)
{
pcb[i].waitingtime=pcb[i].starttime-pcb[i].arrivaltime; //等待时间=开始时间-到达时间
pcb[i].cycletime=pcb[i].finishtime-pcb[i].arrivaltime; //周转时间=完成时间-到达时间
pcb[i].wctime=pcb[i].cycletime/(pcb[i].runtime*1.0); //带权周转时间=周转时间/运行时间
}
/*平均周转时间 平均带权周转时间*/
int sum1=0;
double sum2=0;
for(int i=0;i<n;i++)
{
sum1+=pcb[i].cycletime; //求所有进程周转时间的和
sum2+=pcb[i].wctime; //求有所进程周转时间的和
}
atime=sum1/(n*1.0); //平均周转时间=所有进程周转时间的和/进程数
awtime=sum2/n; //平均带权周转时间=所有进程周转时间的和/进程数
}
/*主函数*/
int main()
{
printf("先来先服务FCFS算法模拟\n请输入进程个数:\n");
int n;
scanf("%d",&n); //输入进程数 n
input(n); //输入函数
rank(n); //排序函数,按到达时间给各进程排序 (升序)
FCFS(n); //先来先服务算法函数,计算各种时间
output(n); //输出函数
return 0;
}
(6) テストデータまたはスクリーンショット:
(6) 実行結果の分析:先着順アルゴリズムに従って、まず到着時刻に従って並べ替えます。プロセスの入力情報によると、最初のプロセス a の到着時刻は 0、そのプロセスの到着時刻は 0、完了時間 = 実行時間 = 1、および残りのプロセス プロセスの完了時間 = 前のプロセスの完了時間 + プロセスの実行時間 (たとえば、 b= 1+100= の完了時間) 101、c=101+1=102の完了時間、d=102+100の完了時間=201)、最初の工程aの開始時間=到着時間=0、他の工程の開始時間=完了前のプロセスの時刻 (例: b の開始時刻 = a の完了時刻 = 1、c の開始時刻 = b の完了時刻 = 101、d の開始時刻 = c の完了時刻 = 102) ; 各プロセスの待ち時間 = 開始時刻 - 到着時刻(例: a の待ち時間 = 0-0 = 0、b の待ち時間 = 1-1=0、c の待ち時間 = 101 -2=99、d=102-3=99の待ち時間);ターンアラウンドタイム=完了時間-到着時間(たとえば、a=1-0=1のターンアラウンドタイム、b=101-1=100のターンアラウンドタイム) 、c=102-2=100のターンアラウンドタイム、d=202-3=199のターンアラウンドタイム);加重ターンアラウンドタイム=ターンオーバー時間/実行時間(例: a=1/1=1の加重ターンアラウンドタイム、 b=100/100=1 の加重ターンオーバー時間、c=100/1=100 の加重ターンオーバー時間、d=199/100= 1.99 の加重ターンオーバー時間) ; 平均所要時間 = すべてのプロセス所要時間の合計/プロセス数(1+100+100+199)/4=100 ; 平均加重所要時間 = すべてのプロセス加重所要時間の合計/プロセス数(1+ 1+100+1.99)/4=26 。
2.タイムスライスラウンドロビンスケジューリングアルゴリズム
(1) アルゴリズムの内容:タイム スライス ラウンドロビン スケジューリング アルゴリズムは主に低レベルのスケジューリングに使用され、スケジューリング方法は実際にはクロックベースのプリエンプティブ スケジューリング アルゴリズムです。タイムスライスラウンドロビンのスケジューリングアルゴリズムを使用するシステムでは、プロセス/スレッドのレディキューが到着時刻順にキューイングされ、先着順の原則に従って、実行する必要のあるすべてのプロセスが順番に配置されます。到着時刻に応じて昇順に並びます。プロセスごとに同じサイズのタイムスライスが与えられます。このタイムスライス内で、プロセスの実行が終了すると、プロセスはプロセスキューから削除されます。プロセスが終了しない場合、プロセスはプロセスキューから削除されます。終了すると、プロセスは停止され、待機状態に変更され、すべてのプロセスの実行が終了するまでプロセス キューの最後尾に置かれます。
(2) アルゴリズム要件:各プロセスはプロセス制御ブロック (PCB) によって表されます。プロセス制御ブロックには、プロセス名、到着時刻、実行時間、完了時刻、ターンアラウンドタイム、承認されたターンアラウンドタイム、完了プロセスフラグ、残りのサービス時間などの情報を含めることができます。プロセスの実行時間はタイム スライスの単位で計算されます。
(3) 設計思想:スケジューリング時には常にレディキューのリーダープロセスを選択し、システムがあらかじめ設定したタイムスライスを CPU 上で実行させます。タイム スライス内で実行が終了していないプロセスは、スレッド キューの最後に戻り、再度キューに入れて次のスケジューリングを待ちます。タイム スライス ラウンドロビン スケジューリングはプリエンプティブ スケジューリングに属し、タイムシェアリング システムに適しています。
(4) アルゴリズム分析:まず RR 構造を定義します。
input() 入力関数;
Rank() 関数はプロセスの到着時間を並べ替えます。
rr_pcb() 関数はラウンドロビン スケジューリング アルゴリズムを実行します。
Output() 出力関数;
main() メイン関数。
(5) コアコード:
#include<stdio.h>
double atime; //平均周转时间
double awtime; //平均带权周转时间
struct RR
{
char name[20]; //进程号
int arrivaltime; //到达时间
int runtime; //运行时间
int starttime; //开始时间
int finishtime; //完成时间
int cycletime; //周转时间
double wctime; //带权周转时间
int sign; //完成进程标志
int st1; //剩余服务时间
};
struct RR rr[100];
/*输入函数*/
int input(int n)
{
printf("请依次输入进程号、到达时间、运行时间:\n");
for(int i=0;i<n;i++)
{
rr[i].sign=0;
scanf("%s\t%d\t%d",rr[i].name,&rr[i].arrivaltime,&rr[i].runtime);
rr[i].st1=rr[i].runtime;
}
}
/*采用冒泡法,按进程的到达时间对进程进行排序*/
int rank(int n)
{
int i,j;
struct RR temp;
for(j=0;j<n-1;j++)
for(i=0;i<n-1-j;i++)
{
if(rr[i].arrivaltime>rr[i+1].arrivaltime)
{
temp=rr[i];
rr[i]=rr[i+1];
rr[i+1]=temp;
}
}
}
/*执行时间片轮转调度算法*/
int rr_pcb(int n)
{
printf("请输入时间片:\n");
int t;
scanf("%d",&t); //输入时间片
int time=rr[0].arrivaltime; //给当前时间time赋初值
int flag=1; //标志就绪队列中有进程
int sum=0; //记录完成的进程数
printf("\n====================================================================================================================\n");
printf("进程号 \t到达时间\t运行时间\t开始时间\t完成时间\t周转时间\t带权周转时间\n");
printf("--------------------------------------------------------------------------------------------------------------------\n");
while(sum<n) //当完成的进程数小于进程总数
{
flag=0; //标记就绪队列没有进程
for(int i=0;i<n;i++) //时间片轮转法执行各进程
{
if(rr[i].sign==1)//已完成进程
continue;
else//未完成的进程
{
if(rr[i].st1<=t && time>=rr[i].arrivaltime)//还需运行的时间小于等于一个时间片
{
flag=1; //把进程加入到就绪队列中
time+=rr[i].st1;
rr[i].sign=1; //此进程完成
rr[i].finishtime=time; //完成时间
rr[i].cycletime=rr[i].finishtime-rr[i].arrivaltime; //计算周转时间=完成时间-到达时间
rr[i].wctime=rr[i].cycletime/(rr[i].runtime*1.0); //计算带权周转时间=周转时间/服务
printf("%3s\t %d\t\t %d\t\t %d\t\t %d\t\t %d\t\t %.2lf\n",rr[i].name,
rr[i].arrivaltime,rr[i].runtime,time-rr[i].st1,time,rr[i].cycletime,rr[i].wctime);
}
else if(rr[i].st1>t&&time>=rr[i].arrivaltime) //还需服务时间至少大于一个时间片
{
flag=1; //把进程加入到就绪队列中
time+=t;
rr[i].st1-=t;
rr[i].cycletime=rr[i].finishtime-rr[i].arrivaltime; //计算周转时间=完成时间-到达时间
rr[i].wctime=rr[i].cycletime/(rr[i].runtime*1.0); //计算带权周转时间=周转时间/服务
printf("%3s\t %d\t\t %d\t\t %d\t\t %d\t\t %d\t\t %.2lf\n",rr[i].name,
rr[i].arrivaltime,rr[i].runtime,time-t,time,rr[i].cycletime,rr[i].wctime);
}
if(rr[i].sign==1)
sum++; //一个进程执行完就+1
}
}
}
/*平均周转时间 平均带权周转时间*/
int sum1=0;
double sum2=0;
for(int i=0;i<n;i++)
{
sum1+=rr[i].cycletime; //求所有进程周转时间的和
sum2+=rr[i].wctime; //求所有进程带权周转时间的和
}
atime=sum1/(n*1.0); //平均周转时间=有进程周转时间的和/进程数
awtime=sum2/n; //平均带权周转时间=所有进程带权周转时间的和/进程数
}
/*输出函数*/
int output(int n)
{
printf("--------------------------------------------------------------------------------------------------------------------\n");
printf("\t平均周转时间 \t\t%.2lf\t\n",atime);
printf("--------------------------------------------------------------------------------------------------------------------\n");
printf("\t平均带权周转时间\t\t%.2lf\t\n",awtime);
printf("====================================================================================================================\n");
}
/*主函数*/
int main()
{
printf("时间片轮转调度算法\n请输入总进程数:\n");
int n;
scanf("%d",&n); //输入总进程数
input(n); //输入函数
rank(n); //排序函数
rr_pcb(n); //计算各时间
output(n); //输出函数
return 0;
}
(6) テスト データまたはスクリーンショット: (タイム スライス 1 については図 1 を参照、タイム スライス 5 については図 2 を参照)
図 1 タイムスライス = 1 の場合の実行結果のスクリーンショット
図 2 タイムスライス = 5 の場合の実行結果のスクリーンショット
(7) 実行結果の分析:実行時間のイメージは次のとおりです。
図4-24 実行時間のイメージ
タイムスライス = 1 の場合、a、b、c、d の 4 つのプロセスの実行時間はいずれも指定されたタイム スライスよりも長いため、タイム スライス内に実行が終了しない場合は、すべて最後まで戻る必要があります。準備完了キューを削除し、次のスケジューリングが実行を継続するのを待ちます。CPU は、現在のレディキューの最初のプロセスに割り当てられます。
タイム スライス = 5 の場合、最初のプロセスの実行時間は 20>5 に等しく、実行時間が 1 つのタイム スライス内に完了しない場合、プロセス a は準備完了キューの最後に戻り、再度キューに入れて次のプロセスを待ちます。スケジューリング; 2 番目のプロセスの実行時間は 10>5 に等しく、指定されたタイム スライスが使い果たされると、プロセス b は準備完了キューの最後に戻り、再び実行のスケジュールが設定されるのを待ちます。プロセスが 15>5 に等しい場合、プロセス c は準備完了キューの最後に戻り、次に自分自身に戻ったときに動作するまで待機します。4 番目のプロセスの実行時間は 5 で、ちょうど1 タイムスライス以内に実行が終了すると、プロセス d は CPU の使用権を放棄します。このとき、プロセス スケジューラは、現在のレディ キューの最初のプロセス、つまりプロセス a に CPU を割り当てます。
3. 優先スケジューリングアルゴリズム
(1) アルゴリズムの内容:優先スケジューリングアルゴリズムは、上位スケジューリング(ジョブスケジューリング)と下位スケジューリング(プロセススケジューリング)の両方に適用でき、リアルタイムシステムでも使用できます。高度なスケジューリングでは、優先順位番号スケジューリング アルゴリズムにより、バックアップ ジョブ キューから最も優先度の高いジョブが選択され、メモリにロードされ、それに対応するリソースが割り当てられ、プロセスが作成されてプロセス準備完了キューに入れられます。低レベルのスケジューリングでは、優先スケジューリング アルゴリズムにより、プロセス準備完了キューから最も優先度の高いプロセスが選択され、そのプロセスに CPU が割り当てられ、実行されます。最も高い優先度を持つジョブ/プロセスが複数ある場合は、先着順または短いジョブ/短いプロセスの優先順位スケジューリング ポリシーと組み合わせることができます。
(2) アルゴリズム要件:各プロセスはプロセス制御ブロック (PCB) によって表されます。プロセス制御ブロックには、プロセス名、実行時間、優先順位番号、プロセスのステータスなどの情報を含めることができます。プロセスの優先順位と実行所要時間は、事前に手動で指定することができます(乱数によって生成することもできます)。各プロセスの状態は、準備完了 W (待機)、実行 R (実行)、または F (終了) の 3 つの状態のいずれかになります。
(3) 設計思想:プリエンプティブ優先スケジューリング アルゴリズムを使用すると、最も高い優先順位を持つ準備完了プロセス/スレッドが最初に CPU を実行し、実行中のプロセス中により高い優先順位を持つ準備完了プロセス/スレッドによってプリエンプトされることが許可されます。最も高い優先度を持つプロセスが複数ある場合は、先着順のスケジューリング ポリシーが結合されます。実行前に、プロセスごとに「優先順位」と「実行所要時間」が任意に決定されます。プロセッサは常に、実行するリーダー プロセスを選択します。優先順位を動的に変更する方式を採用しており、処理を実行するたびに優先順位が1ずつ減り、実行所要時間が1ずつ減少します。プロセスが 1 回実行された後、必要な実行時間が 0 に等しくない場合はキューに追加され、それ以外の場合はステータスが「終了」に変更され、キューが終了します。準備完了キューが空の場合は終了し、そうでない場合は上記の手順を繰り返します。
(4) アルゴリズム分析:プロセス制御ブロックを定義します。
input() 関数;
出力()関数;
max_priority() 関数は、準備完了状態で最も高い優先度を持つプロセスを見つけます。
psa_pcb() 関数は優先順位スケジューリング アルゴリズムです。
main() メイン関数;
(5)コアコード:
#include<stdio.h>
/*结构体*/
struct PSA
{
char name[10]; //进程名
int runtime; //运行时间
int priority; //优先数
char state; //状态,三状态:W-就绪;R-运行;F-结束
};
struct PSA psa[10]; //定义进程控制块数组
/*输入函数*/
int input(int n)
{
printf("请输入PCB的进程名,运行时间,优先数:\n");
for(int i=0;i<n;i++) //i为进程编号
{
scanf("%s\t%d\t%d",&psa[i].name,&psa[i].runtime,&psa[i].priority);
psa[i].state=‘W’; //初始状态都设为就绪
getchar();
}
}
/*输出函数*/
int output(int n)
{
printf("\n==============================\n");
printf("进程号 运行时间 优先数 状态\n");
printf("------------------------------\n");
for(int i=0;i<n;i++)
printf("%s %7d%9d\t%s\n",psa[i].name,psa[i].runtime,psa[i].priority,&psa[i].state);
printf("==============================\n");
}
/*进程在就绪状态时找出最大优先数进程(返回值为最大优先数编号)*/
int max_priority(int n)
{
int max=-1; //max为最大优先数
int m; //m为最大优先数进程的编号
for(int i=0;i<n;i++)
{ //进程在就绪状态时找出最大优先数
if(psa[i].state==‘R’) //进程在运行状态
return -1;
else if((max<psa[i].priority)&&(psa[i].state==‘W’)) //进程在就绪状态
{
max=psa[i].priority;
m=i; //把最大优先数对应的编号赋给m
}
}
//确保最大优先数进程还没结束运行
if(psa[m].state==‘F’) //最大优先数进程已结束运行
return -1;
else //最大优先数进程还没结束运行
return m; //返回值为最大优先数编号
}
/*优先数调度算法*/
int psa_pcb(int n)
{
int max_time=-1,m=0;
int sum=0; //sum为程序总运行次数
for(int i=0;i<n;i++)
sum+=psa[i].runtime;
printf("\n初始时各进程信息如下:\n");
output(n);
getchar();
for(int j=0;j<sum;j++)
{
//当程序正在运行时
while(max_priority(n)!=-1) //max_priority ()为找出最大优先数进程函数,返回最大值对应的编号m
{
if(psa[max_priority(n)].priority!=0)
psa[max_priority(n)].state=‘R’; //由就绪转为运行态
else
{ //当优先级降为0,进程还没运行完时
for(int i=0;i<n;i++)
if(max_time<psa[i].runtime)
{
max_time=psa[i].runtime;
m=i; //返回对应的编号
}
max_time=-1;
psa[m].state=‘R’; //状态转为运行态
}
}
//判断程序状态(对优先数和运行时间操作)
for(int i=0;i<n;i++)
{
if(psa[i].state==‘R’) //当进程处于运行状态时
{
if(psa[i].priority>0) //优先数>0
psa[i].priority--; //每运行一次优先数-1
psa[i].runtime--; //每运行一次运行时间-1
}
if(psa[i].runtime==0) //运行时间完
psa[i].state=‘F’; //进程状态转为完成状态
else //运行时间没完
psa[i].state=‘W’; //进程状态转为就绪状态
}
output(n);
getchar();
}
}
/*主函数*/
int main()
{
printf("优先数调度算法:\n输入总进程数:\n");
int n;
scanf("%d",&n); //输入总进程数n
input(n); //输入函数
psa_pcb(n); //优先数调度算法
return 0;
}
(6) テストデータまたはスクリーンショット:
(7) 実行結果の分析:当初、5 つのプロセス a、b、c、d、e の状態はすべて準備完了状態 (W) にあり、このうち c の優先順位が最も高く、次に c が先にあります。実行状態では、実行時間は 1 減少し、優先順位番号は 1 減少します。プロセス a の実行時間は 0、プロセス a の状態はが準備完了状態から完了状態に変化し、その後、c と e の優先順位番号が最も大きくなりますが、先着順のスケジューリング ポリシーに従って、c が最初に実行状態になると、優先順位番号は によって減らされます。 1となり、実行時間が1減って0になるので、cは完了状態となるが、この時点で準備完了状態にあるのはb、d、eの3つのプロセスのみで、そのうちeの優先順位が最も大きい。次に、e が CPU を取得して動作させ、その実行時間が 1 減り、優先順位番号が 1 減ります。その後、b と e の優先順位は、先着順に従って同じになります。スケジューリング ポリシーを提供すると、b は CPU をプリエンプトして実行状態になります。実行時間が 1 減って 0 になると、b は完了します。この時点では、d と e の 2 つのプロセスだけが残っており、e はより高いプロセスを持っています。優先順位番号の場合、e は CPU をプリエンプトして実行状態になり、優先順位番号と実行時間は 1 減ります。e 優先順位番号から 1 を引いた値は d と同じですが、先着順に従います。 -served 原則では、d が最初に CPU を取得して実行状態になり、優先順位番号と実行時間が 1 減ります。この時点では、e の優先順位番号は d より大きいため、e は CPU Run を取得します。実行時間と優先順位番号から 1 を引いたもの。d と e の優先順位番号は同じですが、d が最初に実行され、実行時間と優先順位番号から 1 を引いた値です。その後、e の優先順位番号が d より大きくなり、e が CPU を取得します。 0、e は完了状態になります。最終的に CPU を実行するには d だけが残り、実行時間が 1 減って 0 になり、完了状態になります。つまり、優先度の高いプロセスがまず実行状態のCPUを獲得し、一度実行すると実行時間と優先度番号が1減り、実行時間が0以外の場合はレディキューに追加されます。実行時間が 0 に等しい場合、状態は終了 (F) に変更されます。同じ優先度のプロセスが複数ある場合は、先着順に処理されます。