線程控制

線程控制

POSIX線程庫

  • 與線程有關的函數構成了一個完整的系列,絕大多數函數的名字都是以“pthread_”打頭的
  • 要使用這些庫函數,要引入頭文件 pthread.h
  • 鏈接這些線程函數庫時要使用編譯器命令“-lpthread” 選項

創建線程:

int pthread_create(pthread_t* thread, const pthread_attr_t* 
attr, void* (*start_routine)(void*), void* arg)

參數:
thread:返回線程ID
attr:設置線程屬性,attr = NULL,表示使用默認屬性
start_routine:是個函數地址,線程啓動後要執行的函數
arg:傳給線程啓動函數的參數
返回值:成功返回0;失敗返回錯誤碼

舉個例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

void *rout(void *arg){
    (void)arg;
    while(1){
        printf("I am thread 1\n");
        sleep(1);
    }
}

int main(void){
    pthread_t tid;
    int ret;
    if((ret = pthread_create(&tid, NULL, rout, NULL)) != 0){
        fprintf(stderr, "pthread_create:%s\n", strerror(ret));
        exit(EXIT_FAILURE);
    }

    while(1){
        printf("I am main thread\n");
        sleep(1);
    }
}

進程ID和線程ID

  • 在Linux中,目前線程實現是Native POSIX Thread Libaray,簡稱NPTL。在這種實現下,線程又被稱爲輕量級進程,每一個用戶態的線程,在內核中對應一個調度實體,也擁有自己的進程描述符(task_struct結構體)。
  • 沒有線程之前,一個進程對應內核裏一個進程描述符,對應一個進程ID。但是引入線程概念之後,一個用戶進程下管轄N個用戶態線程,每個線程作爲一個獨立的調度實體在內核態都有自己的進程描述符,進程和內核的描述符一下變成1 : N的關係,POSIX標準又要求進程內所有線程調用getpid函數時返回相同的進程ID,如何解決上述問題呢?
  • Linux引入了線程組的概念。
struct task_struct {
    ...
    pid_t pid;
    pid_t tgid;
    ...
    struct task_struct* group_leader;
    ...
    struct list_head thread_group;
    ...
  • 多線程的進程,又被稱爲線程組,線程組內的的每一個線程在內核中都有一個進程描述符與之對應。進程描述符中的pid對應線程id;進程描述符中的tgid,含義是Thread Group ID,該值對應的是用戶層面的進程ID。

這裏寫圖片描述

線程ID及進程地址空間佈局

  • pthread_create函數會產生一個線程ID,存放在第一個參數指向的地址中。該線程ID和前面所說的線程ID不一樣。
  • 前面的線程ID屬於進程調度的範疇。因爲線程是輕量級進程,是操作系統調度器的最小單位,所以需要一個數值來唯一標識一個線程。
  • pthread_create函數產生並標記在第一個參數指向的地址中的線程ID中,屬於NPTL線程庫的範疇。線程庫的後續操作,就是根據該線程ID來操作線程的。
  • NPTL提供了pthread_self函數獲得自身ID。
pthread_t pthread_self(void)

這裏寫圖片描述

線程終止

如果要終止某一個進程而不終止整個進程,可以有三種方法:

  1. 從線程函數return。這種方法對主線程不適用,從main函數return相當於調用exit.
  2. 線程可以調用pthread_exit終止自己
  3. 一個線程可以調用pthread_cancle終止同一個進程中的另外一個線程。

Pthread_exit函數

功能:線程終止
原型: void pthread_exit(void* value_ptr)
參數: value_ptr:value_ptr不要指向一個局部變量
返回值: 無返回值

pthread_cancel函數

功能:取消一個執行中的線程
原型: int pthread_cancle(pthread_t thread);
參數:thread:線程ID
返回值:成功返回0;失敗返回錯誤碼

線程等待與分離

線程等待
爲什麼線程需要等待?

  • 已經退出的線程,其空間沒有被釋放,仍然在進程地址空間內。
  • 創建新的線程不會複用剛纔退出線程的地址空間。
功能:等待線程結束
原型:
    int pthread_join(pthread_t thread, void **value_ptr)
參數:
    thread:線程ID
    value_ptr:它指向一個指針,該指針指向線程的返回值。
返回值:成功返回0;失敗返回錯誤碼。

調用該函數的線程將掛起等待,直到id爲thread的線程終止。thread通過不同方法終止,通過phread_join得到的終止碼是不同的。

1.如果thread線程通過return返回,value_ptr所指向的單元裏存放的是thread線程函數的返回值。
2.如果thread線程被別的函數調用phread_cancle異常終止掉,value_ptr所指向的單元裏存放的是常數PThREAD_CANCLEED
3.如果thread線程是自己調用pthread_exit ()終止的,value_ptr所指向的單元存放的是傳給pthread_exit的參數。
4.如果對thread線程的終止狀態不感興趣可以穿參數NULL

發佈了66 篇原創文章 · 獲贊 22 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章