pthreadののLinuxのマルチスレッドプログラミング(転載)

転載元:https://blog.csdn.net/skyroben/article/details/72793409

1.背景

Linuxは、真の意味でのスレッドはありません、その実装はプロセスをシミュレートすることで、それはlibpthreadの共有ライブラリを配置されたユーザレベルスレッド、(そのスレッドIDが唯一のライブラリに有効です)に属し、POSIX標準は、以下の通りです。

スレッドを記述するために正規のWindows、TCBデータ構造があります。

ライブラリとNPTLスレッディング二つの最も有名なのLinuxThreads上のLinux。

 

比較の二つのLinuxスレッドモデル:

Linuxのスレッドモデルの比較

 

Linuxのマルチスレッドの仮想アドレス空間マッピングのvforkを有する複数のサブプロセスを作成することに似ています。

2.プロセスおよびスレッドとの間の差

    プロセス:インスタンスを実行している動的プログラムは、システムリソースの例割り当てを前提としています。(Linuxの実装プロセスの主な目的は、リソース排他的です)

    スレッド:内部プロセスでの分岐実行(プロセスのアドレス空間)を実行し、スケジューリング(LWPをスケジュールすることにより、スケジュール)の基本単位です。(スレッドのLinuxの実装の主な目的は、共有リソースです)

    プロセスが提供するすべてのリソースを通します。

    単一プロセス:唯一のプロセススレッド(LWP = PID)。

    LWP:軽量プロセス。

 

    同じプロセスを共有する複数のスレッドに同じアドレス空間なので、テキストセグメント、データ・セグメントが共有されているので、あなたが関数を定義する場合は、グローバル変数を定義した場合、各スレッドが呼び出すことができますで、あなたはそれぞれのスレッドにアクセスすることができます加えて、各スレッドには、以下のプロセス資源と環境を共有しました。 

1.ファイルディスクリプタテーブル
治療(SIG_IGN、SIG_DFLまたはカスタム信号処理機能)2.各信号  
3.現在の作業ディレクトリ
4.ユーザIDとグループID
 しかし、いくつかのリソース各1の各スレッド:
 1.スレッドID
2.種々のレジスタ、プログラムカウンタおよびスタックポインタの値を含むコンテキスト情報
3.スタック空間
4. errno変数
マスク文字信号
6.スケジューリング優先度

(比較のプロセスと比較して)マルチスレッドプログラムの利点:

1.データの大部分を共有し、互いの間で同じアドレス空間を使用して、複数のスレッドは、そのスレッド開始スペースは、オペレーティング・スペースよりもはるかに小さいかかり、それがプロセスをとり、互いにスレッドの切り替えに要する時間プロセスよりもはるかに少ないの切り替えに要する時間は、高速で破壊を作成します。
2.機構は、スレッド間の通信を容易にすることです。スレッドは、直接他のスレッドに使用することができ、同じプロセス内のスレッドなので、データ間の共有データ空間なので、それが速いだけではなく、また便利。

3.プロセス制御

Linuxシステムでは、スレッドに関連する機能は、ヘッダファイルpthread.hの中で定義されています。

スレッド関数--pthread_create機能を作成します。

書式#include <pthread.hの>
 int型のpthread_create(がpthread_t *スレッド、constの pthread_arrt_tの* attrの、無効 *(* start_routineが)(ボイド *)、無効 * argに)
(1)スレッド引数は整数として、新しいスレッド識別子です。
(2)ATTRパラメータは、新しいスレッドのプロパティを設定します。NULLを渡すには、デフォルトのスレッド属性として表現しました。
(3)start_routineはとのargパラメータは、関数を指定し、パラメータは、新しいスレッドが実行されますされています。start_routineがリターンは、このスレッドから撤退すると
(4)戻り値:成功時に0を返し、エラー番号を返すために失敗したことを。
 
    タイプのスレッドIDは、異なるシステム上の異なる実装を持って、pthread_self()を呼び出しidは、現在のスレッドを取得することができ、このタイプのthread_tの、唯一の現在のプロセスが一意であることを確実にするために、thread_tのです
    タイプpid_tプロセスIDは、各プロセスのIDは、現在のプロセスを得ることができる()IDをGETPID呼び出し、システム全体で一意である場合、それは、正の整数値です。

スレッド--pthread_cancel機能と関数pthread_exitを終了

全体のプロセスを終了させることなく、スレッドを終了し、3つの方法があります。
スレッド関数からの復帰1。このメソッドは、メインスレッドには適していない、主な機能は、出口を呼び出すのと同じ返します。
2.スレッドは、同じプロセス内の他のスレッドを終了するのpthread_cancel呼び出すことができます。
3.スレッドは、それ自体を終了pthread_exit呼び出すことができます。
 
#include <pthread.hの> INTのpthread_cancel(がpthread_tスレッド)。
 
(1)スレッドパラメータは、ターゲットスレッド識別子です。
(2)この関数は成功時に0を返し、失敗のエラーコードが返されます。
 
書式#include <pthread.hの> 無効 pthread_exit(無効 RETVAL *);
 
(1)のretvalがvoid *型である、他のスレッドは、このポインタを取得pthread_joinの呼び出すことができます。他のスレッドが取得するときに機能が引き出されたスレッドへのポインタを返すので、スレッド関数のスタックに割り当てることができないポインタポイントは、グローバルまたはmalloc関数によって割り当てられなければなりません返されたメモリセルというか、pthread_exitを返すことが注目されます。
(2)リサイクルへの出口情報RETVALスレッドパラメータを通過するように機能するpthread_exit。実行した後、それを呼び出し元に戻らないと、失敗することはありません。

スレッドが待機--pthread_join

書式#include <pthread.hの> 無効 pthread_joinを(がpthread_tスレッド、のretval **)。
 
(1)関数は、スレッドIDがスレッドとして終了するまで、スレッドのハングを待つと呼ばれています。
(2)スレッドが異なる方法でスレッドを終了するには、得られた状態pthread_joinを終端することによって、異なります
 
次のように要約:
1.場合尖ったスレッドが機能スレッドの戻り値に格納されvalue_ptrユニットに戻すスレッド戻り、スルースレッド。
店舗で指摘value_ptr他端オフユニットはPTHREAD_CANCELED一定であるのpthread_cancelスレッドスレッドスレッド例外が呼び出された場合2。
3.スレッドはスレッドである場合pthread_exitが終了し、自分自身を呼び出し、value_ptr尖ったユニットはpthread_exitために渡されたパラメータに格納されます。あなたがスレッドを終了するスレッドの状態に興味がない場合は、パラメータをvalue_ptrするNULLを渡すことができます。

(3)エラーコードを返すために失敗、成功時に0を返します。エラーコードが発生する可能性があります。

4.分離スレッド

 1時間のいずれかの時点で、スレッドは、結合(連結可能)または分離(剥離)されます。
 2.スレッドの組み合わせは、そのリソースを撤回し、他のスレッドを殺すことができます。他のスレッドによって回収される前に、そのメモリリソース
(例えばスタック)は解放されません。(例スレッドの下で、デフォルトで作成された組合せ可能です) 
 3.別のスレッドはリサイクルまたはそれが終了したときに、システムによって自動的にメモリリソースを解放し、別のスレッドを殺すことはできません。
 4.結合スレッド実行の最後ではなく、参加した場合、いくつかのリソースがそう実行し、スレッドの終了コードを取得し、そのリソースを回復するために、スレッドの終了を待つpthread_joinを呼び出す必要があり、スレッドを作成し、リサイクルされない原因となります。 
      
调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞。如何解决这种情况呢?      
    例如,在Web服务器中当主线程为每个新来的连接请求创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的连接请求),这时可以在子线程中加入代码 pthread_detach(pthread_self())或者父线程调用pthread_detach(thread_id)(非阻塞,可立即返回)这将该子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源。
 
验证代码:
#include <stdio.h>
#include <error.h>
#include <stdlib.h>
#include <pthread.h>

void* thread_run(void* _val)
{
    pthread_detach(pthread_self()); //注释这句代码join success
    printf("%s\n", (char*)_val);
    return NULL;
}

int main(){
    pthread_t tid;
    int tret = pthread_create(&tid, NULL, thread_run, "thread_run~~~~~");
    //线程创建成功之后,程序的执行流变成两个,一个执行函数thread_run,一个继续向下执行。
    if (tret == 0){
        sleep(1);
        int ret = pthread_join(tid, NULL);
        if (ret == 0){
            printf("pthread_join success\n");
            return ret;
        }else{
            printf("pthread_join failed info: %s\n", strerror(ret));
            return ret;
        }
    }else{
        printf("create pthread failed info: %s", strerror(tret));
        return tret;
    }
}                        
运行结果:
分析:
可以看到被分离的线程不可以被等待;一个线程初始为可结合的,要么在父线程等待或分离,要么在子线程分离,只能采取上述几种措施的一种。

おすすめ

転載: www.cnblogs.com/leokale-zz/p/11135089.html