wait_on_buffer解析


Linux-0.12コードは次のとおりです.
static inline void wait_on_buffer(struct buffer_head * bh)
{
    cli();    /* */
    while (bh->b_lock)    /* */
        sleep_on(&bh->b_wait);    /* 1 
                         , 1 */
    sti();
}

自分の質問:
なぜcli()とsti()が必要なのか、削除してはいけません.while(bh->b_lock) if(bh->b_lock)行だめwait_を呼び出すとon_bufferのプロセスはオフ割り込み中に一時停止され、他のプロセスはシステムで正常に実行できますか?
次のように分析されます.
まずはwait_を明確にon_bufferはカーネル状態で動作する関数であり,その呼び出しには2つの可能性がある.
ユーザ状態プロセスは、デバイスにデータを要求し、カーネル状態に入るとトリガーされるカーネル状態自体の操作がトリガーされたのは、カーネル状態にあるプロセス呼び出しのであるに違いない.

cli()とsti()はwait_on_bufferは臨界領域の役割を果たし、この2つの関系中断と開中断の関数がなければいいですか?wait_on_bufferはカーネル状態で動作し、cli()はクロック割り込み、ハードディスク割り込みなど、すべてのシールド可能な割り込みをオフにします.これは、次のことを意味します.
現在実行wait_on_bufferのプロセスは、タイムスライスが到着したためにスケジューラによって回転されず、while(bh->b_lock)の実行が保証され、この関数の実行中にbh->b_に対する他のプロセスはありません.lockは、いくつかの不要なエラーを回避するために修正されましたb_lockは、ブロックデバイスドライバがデバイス内のデータにアクセスする場合に、ドライバによってロック解除されることを示す.したがって、このプロセスは、申請されたバッファがロックされて保留された後、ハードディスクなどのブロックデバイスのデータが到着すると、b_ロックはロックを解除し、保留中のプロセスは再スケジュールによってバッファを取得する.ここでは、バッファにロックは付加されていないことに注意する.
while(bh->b_lock)if(bh->b_lock)であり、現在のプロセスがAであり、bh->lockがロックされていると仮定すると、プロセスAはスリープ状態に入り、hbの待機キューに掛けられ、スケジューラによってプロセスBに呼び出されて実行される.プロセスBの実行中、外部ブロック装置のデータ転送が完了したためhb->lockがロック解除され、buffer unlock後、キューヘッダのプロセスAが起動すると、タイムスライスがプロセスBにあり、Bはそのbuffer unlockを発見し、lockし、その後、タイムスライスを自発的に放棄し、再スケジュールに入る.スケジューラはAをif(bh->lock)であるためbh->lockロックのチェックをせずにそのまま割り込み運転を継続する.このとき、A、Bの2つのプロセスの状態は、Aが実行状態にあり、buffer hdが他のプロセスにロックされていないと判断し、hdプロセスの操作を継続する.プロセスBは、準備/ブロック/保留状態にあり、buffer hdがロックされ、システムの不一致をもたらす.while(bh->b_lock)を使用すると、プロセスAが起動して再呼び出しされた場合、bh->b_をもう一度呼び出す必要があります.ロックがチェックする、まだロックされていることが発見されると、再び保留状態に入り、システムの一貫性が保証される.
質問:wait_を呼び出すとon_bufferのプロセスはオフ中断中に停止されましたが、他のプロセスはシステムで正常に動作しますか?この問題の答えは、他のプロセスの正常な動作に影響を与えないことです.なぜならsleep_onこのプロセスを保留すると、スケジューラが再スケジュールされ、新しいプロセスをCPUに入れて実行する場合、現在のプロセスのコンテキストプロセスを保存する必要があります.もちろんEFLAGSも含まれますが、cli()が変更されたのはEFLAGSのIFビットです.すなわち,新たに切り替わったプロセスは自己の既存のEFLAGSを用い,既存のIFは開割り込み状態であり,この場合は開割り込み状態であり,元はオフ割り込み状態であり,この場合はオフ割り込み状態であり,以前のプロセスの割り込みがオンになったかどうかとは無関係である.
また、cli()がオフになっていると、クロックの割り込みが遮断され、クロック情報が失われるという問題が発生します.カーネルがこの問題を解決する方法は、オフになっているとjiffiesが失われ、後でTSCレジスタを読み直すことで再設定されます!rt_を呼び出すrequest_linux_IRq Linuxの割り込みサービスプログラムrecover_を登録するjiffies,この割り込みプログラムとLinuxのクロック割り込みサービスプログラムはクロック割り込みを共有し,recover_jiffiesは、Linuxが失われたクロック割り込みを補償するために使用されます(リアルタイムタスクの実行により、Linuxが長時間実行する機会が得られず、クロック割り込みに応答できない可能性があります).