デバイスドライバの1つ-linux信号量semaphore
2102 ワード
転載先:http://soft.yesky.com/os/lin/10/2303010_2.shtml
信号量(semaphore)Linuxカーネルの信号量は、概念的かつ原理的にユーザ状態のSystem VのIPCメカニズム信号量と同じであるが、カーネル以外では使用できないため、System VのIPCメカニズム信号量とは無関係である.信号量は作成時に初期値を設定する必要があり、同時にいくつかのタスクがこの信号量保護の共有リソースにアクセスできることを示し、初期値が1であれば反発ロック(Mutex)になり、すなわち信号量保護の共有リソースにアクセスできるタスクは同時に1つしかない.1つのタスクが共有リソースにアクセスするには、まず信号量を取得しなければならない.信号量を取得する操作は信号量の値を1減少させ、現在の信号量の値が負数であれば、信号量を取得できないことを示し、そのタスクは信号量の待機キューに掛けて信号量が利用可能になるのを待たなければならない.現在の信号量の値が負でない場合、信号量が得られることを示すので、その信号量によって保護された共有リソースに直ちにアクセスすることができる.タスクが信号量によって保護された共有リソースにアクセスした後、信号量を解放しなければならない.解放信号量は、信号量の値に1を加えることによって実現され、信号量の値が非正数である場合、現在の信号量を待つタスクがあることを示すため、信号量を待つすべてのタスクを呼び覚ます.信号量のAPIは以下の通りである.
マクロは、信号量nameを宣言し、その値を0に初期化し、すなわち、反発ロックを宣言する.
マクロは反発ロックnameを宣言しますが、初期値を0に設定します.つまり、ロックは作成時にロックされた状態にあります.従って、このロックについては、一般的には、先に解放された後に得られる.
この関数は、信号量semの値をvalに設定する設定信号量の初期値を数えるために使用される.
この関数は、信号量semの値を1に設定する反発ロックを初期化するために使用される.
この関数は、反発ロックを初期化するためにも使用されますが、信号量semの値を0に設定します.つまり、最初はロックされた状態です.
この関数は、睡眠を引き起こす信号量semを得るために使用され、IRQコンテキストおよびsoftirqコンテキストを含む割り込みコンテキストでは使用できません.この関数はsemの値を1に減らし、信号量semの値が負でない場合は直接戻ります.そうしないと、呼び出し者は別のタスクが信号量を解放してから実行を継続するまで保留されます.
この関数の機能はdownと似ていますが、downは信号(signal)で中断されませんが、down_interruptibleは信号によって遮断されることができるので、この関数は正常に戻るか信号によって中断されるかを区別するために戻り値があり、0を返すと、信号量が正常に戻ることを示し、信号によって遮断されると、EINTRに戻る.
この関数は、信号量semを取得してみて、すぐに取得できれば、信号量を取得して0を返し、そうでなければ、信号量semを取得できないことを示し、0以外の値を返します.したがって、呼び出し者の睡眠を招くことなく、コンテキストを中断して使用することができます.
この関数は信号量semを解放し、すなわちsemの値を1加算し、semの値が非正数である場合、信号量を待つタスクがあることを示し、これらの待機者を呼び覚ます.
信号量(semaphore)Linuxカーネルの信号量は、概念的かつ原理的にユーザ状態のSystem VのIPCメカニズム信号量と同じであるが、カーネル以外では使用できないため、System VのIPCメカニズム信号量とは無関係である.信号量は作成時に初期値を設定する必要があり、同時にいくつかのタスクがこの信号量保護の共有リソースにアクセスできることを示し、初期値が1であれば反発ロック(Mutex)になり、すなわち信号量保護の共有リソースにアクセスできるタスクは同時に1つしかない.1つのタスクが共有リソースにアクセスするには、まず信号量を取得しなければならない.信号量を取得する操作は信号量の値を1減少させ、現在の信号量の値が負数であれば、信号量を取得できないことを示し、そのタスクは信号量の待機キューに掛けて信号量が利用可能になるのを待たなければならない.現在の信号量の値が負でない場合、信号量が得られることを示すので、その信号量によって保護された共有リソースに直ちにアクセスすることができる.タスクが信号量によって保護された共有リソースにアクセスした後、信号量を解放しなければならない.解放信号量は、信号量の値に1を加えることによって実現され、信号量の値が非正数である場合、現在の信号量を待つタスクがあることを示すため、信号量を待つすべてのタスクを呼び覚ます.信号量のAPIは以下の通りである.
DECLARE_MUTEX(name)
マクロは、信号量nameを宣言し、その値を0に初期化し、すなわち、反発ロックを宣言する.
DECLARE_MUTEX_LOCKED(name)
マクロは反発ロックnameを宣言しますが、初期値を0に設定します.つまり、ロックは作成時にロックされた状態にあります.従って、このロックについては、一般的には、先に解放された後に得られる.
void sema_init (struct semaphore *sem, int val);
この関数は、信号量semの値をvalに設定する設定信号量の初期値を数えるために使用される.
void init_MUTEX (struct semaphore *sem);
この関数は、信号量semの値を1に設定する反発ロックを初期化するために使用される.
void init_MUTEX_LOCKED (struct semaphore *sem);
この関数は、反発ロックを初期化するためにも使用されますが、信号量semの値を0に設定します.つまり、最初はロックされた状態です.
void down(struct semaphore * sem);
この関数は、睡眠を引き起こす信号量semを得るために使用され、IRQコンテキストおよびsoftirqコンテキストを含む割り込みコンテキストでは使用できません.この関数はsemの値を1に減らし、信号量semの値が負でない場合は直接戻ります.そうしないと、呼び出し者は別のタスクが信号量を解放してから実行を継続するまで保留されます.
int down_interruptible(struct semaphore * sem);
この関数の機能はdownと似ていますが、downは信号(signal)で中断されませんが、down_interruptibleは信号によって遮断されることができるので、この関数は正常に戻るか信号によって中断されるかを区別するために戻り値があり、0を返すと、信号量が正常に戻ることを示し、信号によって遮断されると、EINTRに戻る.
int down_trylock(struct semaphore * sem);
この関数は、信号量semを取得してみて、すぐに取得できれば、信号量を取得して0を返し、そうでなければ、信号量semを取得できないことを示し、0以外の値を返します.したがって、呼び出し者の睡眠を招くことなく、コンテキストを中断して使用することができます.
void up(struct semaphore * sem);
この関数は信号量semを解放し、すなわちsemの値を1加算し、semの値が非正数である場合、信号量を待つタスクがあることを示し、これらの待機者を呼び覚ます.