Linuxプロセスを一歩一歩理解する(6)-スレッド

5075 ワード

スレッドとスレッドID


「Linuxプロセスを一歩ずつ理解する(1)-プロセスの基礎知識」で説明しました.
カーネルにはスレッドという概念はありません.Linuxはすべてのスレッドをプロセスとして実現し,スレッドは1つだけと見なされる.
他のプロセスとリソースを共有するプロセス.
以下のスレッドについての議論は、POSIXの基準に基づいている.
プロセスのidはpid_t構造で表され、同様にスレッドのidはpthread_t構造で表される.具体的な値はpthread_self関数によって得ることができ、pthread_t間の比較はpthread_equal関数によって実現される.
#include <pthread.h>

pthread_t pthread_self(void);

int pthread_equal(pthread_t tid1, pthread_t tid2);

スレッドの作成


新しいスレッドは、pthread_create関数を使用して作成されます.
#include <pthread.h>

int pthread_create(pthread_t *restirct tidp,

                   const pthread_attr_t *restrict attr,

                   void *(*start_rtn)(void), void *restrict arg);

/*      0,         */

パラメータは次のように解釈されます.
  • tidpが指すメモリユニットは、新しいスレッドのidに格納される.
  • attrは、スレッドによって作成されたいくつかのプロパティを表し、後で説明します.
  • start_rtnは、新しいスレッドが作成された後に実行される関数を示す関数のアドレスです.
  • argは、start_rtn関数のパラメータのポインタを表す.

  • スレッド終了


    プロセスの終了には、次の3つの方法があります.
    1.起動時に実行された関数から戻ります.戻り値はスレッドの終了コードです.2.スレッドはpthread_exit関数を呼び出します.3.同じプロセスの他のスレッドによってキャンセルされます.
    #include <pthread.h>
    
    void pthread_exit(void *rval_ptr);
    rval_ptrはタイプレスポインタであり、スレッドがその起動ルーチンから返された場合、rval_ptrをintに強制的に変換して、スレッドの戻りコードを表すことができる.プロセス内の他のスレッドは、pthread_join関数を使用してこのアドレスにアクセスできます.
    #include <pthread.h>
    
    int pthread_join(pthread_t thread, void **rval_ptr);

    呼び出しスレッドは、指定したスレッドが終了するまでブロックされます.
    スレッドは、pthread_cancel関数を使用して、同じプロセス内の他のスレッドのキャンセルを要求できます.
    #include <pthread.h>
    
    int pthread_cancel(pthread_t tid);

    スレッド同期


    カーネル内の同期は、Linuxのカーネル同期を一歩一歩理解する POSIXを参照しても同様の同期方法を定義することができる.

    はんぱつりょう


    反発量用pthread_mutex_tデータ型は、使用前に初期化が必要であることを示し、これを定数PTHREAD_MUTEX_INITIALIZER(静的に割り当てられた反発量のみ)に設定するか、pthread_mutex_init関数によって初期化することができる.破壊された反発量は、pthread_mutex_destroy関数を使用することができる.
    #include <pthread.h>
    
    int pthread_mutex_init(pthread_mutex_t *restrict mutex,
    
                           const pthread_mutexattr_t *restrict attr);
    
    int pthread_mutex_destroy(pthread_mutex_t *mutex);

    パラメータattrは反発量のパラメータを表し、デフォルトのパラメータを使用してNULLに直接設定すればよい.
    次の3つの関数は、反発量を取得し、反発量を解放するために使用されます.
    #include <pthread.h>
    
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    
    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    
    int pthread_mutex_unlock(pthread_mutex_t *mutex);

    リードライトロック


    カーネルの「読み書きスピンロック」と同様に、書き込みプロセスの飢餓を引き起こす可能性があります.主な操作関数は次のとおりです.
    #include <pthread.h>
    
    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
    
                            const pthread_rwlockattr_t *restrict attr);
    
    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
    
    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
    
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
    
    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
    
    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
    
    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

    じょうけんへんすう


    条件変数は、pthread_cond_t構造によって表される複数のスレッドに合流する場所を提供し、それ自体は反発量を保護する必要がある.待機条件がまだ成立していない場合、スレッドは1つのキューに配置され、この条件が満たされるまで、キュー内の1つのスレッドを起動するか、すべてのスレッドを起動するかを選択できます.
    1つの条件変数をPTHREAD_INITIALIZERに静的に初期化してもよいし、次の関数を使用して条件変数を初期化して破棄してもよい.
    #include <pthread.h>
    
    int pthread_cond_init(pthread_cond_t *restrict cond,
    
                          pthread_cond_attr *restrict attr);
    
    int pthread_cond_destroy(pthread_cond_t *cond);

    次の2つの関数は、スレッドに特定の条件変数を待機させ、反発量を使用して保護することに注意します.後者にはタイムアウト時間のパラメータがありますが、この時間を超えると条件が成立しなくても返されます.
    #include <pthread.h>
    
    int pthread_cond_wait(pthread_cond_t *restrict cond,
    
                          pthread_mutex_t *restrict mutex);
    
    int pthread_cond_timewait(pthread_cond_t *restrict cond,
    
                              pthread_mutex_t *restrict mutex,
    
                              const struct timespec *restrict timeout);

    次の2つの関数は、スレッドが条件を満たしていることを通知するために使用されます.
    #include <pthread.h>
    
    int pthread_cond_signal(pthread_cond_t *cond);
    
    int pthread_cond_broadcast(pthread_cond_t *cond);
    pthread_cond_broadcastは、この条件変数がキュー上のすべてのスレッドを待機していることを起動し、pthread_cond_signalはそのうちの1つだけを起動します.
    JH, 2013-05-15
    参考資料:
  • 『UNIX環境高度プログラミング』
  • 「Linuxカーネル設計と実装」
  • 『Linuxカーネルを深く理解する』