系統編程——線程學習筆記

守護進程:
    daemon進程,通常運行於操作系統後臺,脫離控制終端。一般不與用戶直接交互。
    週期性的等待某個事件發生或週期性執行某一動作。
    不受用戶登錄註銷影響,通常採用以d結尾的命名方式

守護進程創建步驟:
    1、fork子進程,讓父進程終止
    2、子進程調用setsid()創建新會話
    3、通常根據需要,改變工作目錄位置chdir()  (防止目錄被卸載)
    4、通常根據需要,重設umask文件權限掩碼        (影響新文件的創建權限)
    5、通常根據需要,關閉/重定向 文件描述符
    6、守護進程 業務邏輯。while()

線程概念:
    進程:有獨立的 進程地址空間,有獨立的pcb。        分配資源的最小單位
    線程:有獨立的pcb,沒有獨立的進程地址空間。
    ps -Lf 進程Id  ---->線程號。LWP --->cpu執行的最小單位。
    
線程共享:
    獨享 棧空間(內核棧、用戶棧)
    共享./text./data ./rodata ./bass heap  -->全局變量

線程控制原語:
    pthread_t pthread_self(void); 
        獲取線程id。線程id是在進程地址空間內部,用來標識線程身份的id號
        返回值:本線程 id
    
    檢查出錯返回:線程當中用
        fprintf(stderr,"xxxxxx %s\n", strerror(ret));
        
    pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_rountn)(void*), void *arg);
        參數1:傳出參數,表新創建的子線程id
        參數2:線程屬性,傳NULL表使用默認屬性
        參數3:子線程回調函數,創建成功,pthread_create函數返回時,該函數會被自動調用
        參數4:參3的參數,沒有的話,傳NULL
    返回值:
        成功:0
        失敗:errno
    
    循環創建N個子線程:
        for(i=0;i<5;i++)
            pthread_create(&tid, NULL, tfn, (void*)i); //將int類型i,強轉成void*,傳參
    
    void pthread_exit(void* retval); 退出當前線程
        retval:退出值,無退出值時,NULL
        
        exit():退出當前進程
        return:返回到調用者那裏去
        pthread_exit():退出當前線程
    int pthread_jion(pthread_t thread, void **retval); //回收線程
        thread:待回收的線程iD
        retval:傳出參數,回收的那個線程的退出值
        返回值:
            成功:0
            失敗:errno
    int pthread_detach(pthread_t thread)    //設置線程分離
        thread:待分離的線程id
        返回值:    
            成功:0
            失敗:errno
    int pthread_cancel(pthread_t thread);//殺死一個線程,需要到達取消點(保存點)
        thread:待殺死的線程id
        返回值:    
            成功:0
            失敗:errno
        如果,子線程沒有到達取消點,那麼pthread_cancel無效
        我們可以在線程中,手動添加一個取消點,使用pthread_testcancel();
        成功被pthread_cancel 殺死的線程,返回 -1, 使用pthread_join回收

        線程控制原語:        進程控制原語
        pthread_create        ->fork()
        pthread_self        ->getpid()
        pthread_exit()        ->exit() 
        pthread_join()        ->wait/waitpid()
        pthread_cancel()    ->kill()
        pthread_detach()    
線程屬性:
    設置分離屬性:
    pthread_attr_t attr        創建一個線程屬性結構體變量
    pthread_attr_init(&attr)    初始化線程屬性
    pthread_attr_setdatachstate(&attr,     PTHREAD_CARETE_DETACH);//設置線程屬性爲分離態
    pthread_carete(&tid, &attr, tfn, NULL) 藉助修改的,設置線程屬性 創建爲分離態的新線程
    pthread_attr_destory(&attr)    銷燬線程屬性

線程同步:
    協同步調,對公共區域數據按序訪問,防止數據混亂,產生於時間有關的錯誤。

鎖的使用:
    建議鎖!對公共數據進行保護。所有線程【應該】在訪問公共數據前先拿鎖再訪問,但 鎖本身不具備強制性
使用mutex(互斥鎖、互斥量)一般步驟:
    1、pthread_mutex_lock:創建鎖
    2、pthread_mutex_init:初始化
    3、pthread_mutex_lock:加鎖
    4、訪問共享數據
    5、pthread_mutex_unlock:解鎖
    6、pthread_mutex_destroy:銷燬鎖
    
    初始化互斥量:
        pthread_mutex_t mutex;
        1、pthread_mutex_init(&mutex, NULL)        動態初始化
        2、pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER  靜態初始化
        
    注意事項:
        儘量保證鎖的粒度,越小越好。(訪問共享數據前,加鎖;訪問結束後【立即】解鎖)
        互斥鎖,本質是結構體。我們可以看成整數。初值爲1(pthread_mutex_init()函數調用成功)
        加鎖:--操作,阻塞線程
        解鎖:++操作,喚醒阻塞在鎖上的線程
        try鎖:嘗試加鎖,成功--。失敗,返回。同時設置錯誤號EBUSY

restrict關鍵字:
    用來限定指針變量,被該關鍵字限定的指針變量所指向的內存操作,必須由本指針完成

【死鎖】:
    是使用鎖不恰當導致的現象:
        1、對一個鎖反覆lock
        2、兩個線程,各自持有一把鎖,請求另一把
讀寫鎖:
    鎖只有一把,            以讀方式給數據加鎖--讀鎖。以寫方式給數據加鎖==寫鎖
    讀共享,寫獨佔
    寫鎖優先級高
    相較於互斥量而言,當讀線程多的時候,提高訪問效率。
    pthread_rwlock_t rwlock;
    pthread_rwlock_init(&rwlock, NULL);
    pthread_rwlock_rdlock
    pthread_rwlock_wrlock
    pthread_rwlock_unlock
    pthread_rwlock_destroy

條件變量:
    本身不是鎖!但是通常結合鎖來使用(mutex)
    pthread_cond_t cond;
    初始化條件變量:
        1、pthread_cond_init(&cond, NULL); 動態初始化
        2、pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 靜態初始化
    阻塞等待條件:
        pthread_cond_wait(&cond, &mutex);
        作用:
            1)阻塞等待條件變量滿足
            2)解鎖已經加鎖成功的信號量(相當於pthread_mutex_unlock(&mutex))
            3)當條件滿足,函數返回時,重新加鎖信號量(相當於pthread_mutex_lock(&mutex))
            
    pthread_cond_signal():喚醒阻塞在條件變量上的(至少)一個線程
    pthread_cond_broadcast():喚醒阻塞在條件變量上的所有線程
    【要求:能夠藉助條件變量,完成生產者消費者問題】

信號量:        
    應用於線程、進程間同步
    相當於 初始化值爲N的互斥量。N值 表示可以同時訪問共享數據區的線程數
    函數:
        sem_t sem;    定義類型
        int sem_init(sem_t *sem, int pshared, unsigned int value)
        參數:
            sem:信號量
            pshared:0:用於線程間同步
                     1:用於進程間同步
            value:N值(指定同時訪問的線程數)
    sem_destroy();
    sem_wait()        一次調用,做一次--操作,當信號量的值爲0時,再次--就會阻塞。(對比pthread_mutex_lock)
    sem_post()        一次調用,做一次++操作,當信號量的值爲N是,再次++就會阻塞。(對比pthread_mutex_unlock)
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章