linux C--多線程的進階使用

線程和多線程

頭文件:<pthread.h>

函數(shù)原型:int pthread_create(pthread_t restrict tidp,const pthread_attr_t restrict_attr,voidstart_rtn)(void*),void *restrict arg);

參數(shù)及返回值:
第一個參數(shù)為指向線程文件句柄的指針。
第二個參數(shù)用來設(shè)置線程屬性。
第三個參數(shù)是線程運行函數(shù)的地址。
最后一個參數(shù)是運行函數(shù)的參數(shù)。
若成功則返回0,否則返回出錯編號

鏈接動態(tài)庫:libpthread.so

實際使用中第二個參數(shù)和最后一個參數(shù)可設(shè)置為NULL或數(shù)字0

信號量

頭文件:<sys/signal.h> #Linux系統(tǒng)下的多線程遵循POSIX線程接口,這是屬于系統(tǒng)調(diào)用的相關(guān)方法

使用也比較簡單,就是設(shè)置好相應(yīng)的參數(shù)就可以了,主要是了解對于參數(shù)的含義,沒有必要全部了解,知道常用的就可以了,比如本次Demo中會用到的幾個我都會仔細說明。
SIGINT:
程序終止(interrupt)信號, 在用戶鍵入INTR字符(通常是Ctrl-C)時發(fā)出,用于通知前臺進程組終止進程。

SIGQUIT:
和SIGINT類似, 但由QUIT字符(通常是Ctrl-)來控制. 進程在因收到SIGQUIT退出時會產(chǎn)生core文件, 在這個意義上類似于一個程序錯誤信號。

SIGTERM:
程序結(jié)束(terminate)信號, 與SIGKILL不同的是該信號可以被阻塞和處理。通常用來要求程序自己正常退出,shell命令kill缺省產(chǎn)生這個信號。如果進程終止不了,我們才會嘗試SIGKILL。

SIGSTOP
停止(stopped)進程的執(zhí)行. 注意它和terminate以及interrupt的區(qū)別:該進程還未結(jié)束, 只是暫停執(zhí)行. 本信號不能被阻塞, 處理或忽略

SIG_BLOCK:
按照參數(shù) set 提供的屏蔽字,屏蔽信號。并將原信號屏蔽保存到oldset中。

SIG_UNBLOCK:
按照參數(shù) set 提供的屏蔽字進行信號的解除屏蔽。針對Set中的信號進行解屏。

SIG_SETMASK:
按照參數(shù) set 提供的信號設(shè)置重新設(shè)置系統(tǒng)信號設(shè)置。

這里咋們先實現(xiàn)一個小的信號Demo

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void* func(void* temp)
{
    printf("~~^o^~~\n");

}

int main()
{
    signal(SIGINT,func);

    while(1)
    {
        printf("sleeping.......\n");
        sleep(1);
    }
    return 0;
}

這里運行程序按下ctr+c本來可以中斷程序,但是信號的處理函數(shù)被我們換成自定義的了,就會執(zhí)行func函數(shù)下的操作,這時候可以用ctr+\強制結(jié)束程序,相當(dāng)于發(fā)送信號SIGQUIT。

如何設(shè)計實用的多線程場景

在實際項目開發(fā)中使用多線程是很小心的,要注意各種問題,主要還是和需求相關(guān),比如線程的mask信息是繼承自進程,多個線程的資源管理問題,信號處理問題,文件鎖問題。

#include<signal.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>

void *  thread_sig_wait(void *tmp)
{
    int ret,signo;
    pthread_t ptid;
    //指定被主進程mask的信號,監(jiān)聽并處理
    sigset_t sig;
    sigemptyset(&sig)

    sigaddset(&sig,SIGINT);
    sigaddset(&sig,SIGQUIT);
    sigaddset(&sig,SIGTERM);

    pthread_t pid = pthread_self();
    pthread_detach(ptid);

    ret  = sigwait(&sig,&signo);
    printf("ret = %d  signo = %d \n",ret,signo);
}

void *  func(void *temp)
{
    pthread_t pid =  pthread_self();
    while(1)
    {
        printf("(^_^)! pid = %lld\n",(long long)pid);
        sleep(1);
    }
}

int main()
{
    pthread_t uid;
    sigset_t sig,osig;
    //設(shè)置線程mask信號集
    //在這里設(shè)置進程需要mask的三個信號,這樣程序就不會被輕易的干掉
    //而洗后開啟的線程同樣繼承了主進程的mask,所以線程也捕捉不到這三個信號
    //這樣我們再用一個管理線程去添加這三個信號量,捕捉以后可以作其他動作,同時detach,將線程的生命周期和資源與主進程分離
    sigemptyset(&sig);
    sigemptyset(&osig);
    sigaddset(&sig,SIGINT);
    sigaddset(&sig,SIGQUIT);
    sigaddset(&sig,SIGTERM);
      
    pthread_sigmask(SIG_BLOCK,&sig,&osig);
    //開啟等待線程

    pthread_create(&uid,0,thread_sig_wait,0);

    //開啟多個工作線程
    for(int i=0;i<5;i++)
    {
        pthread_t pid;
        pthread_create(&pid,0,func,0);
    }

    while(1)
    {

    }

    printf("主函數(shù)退出!\n");
    return 0;
}

說明:
pthread_detach()
1)pthread_detach()即主線程與子線程分離,子線程結(jié)束后,資源自動回收。
2)函數(shù)說明

函數(shù)原型:int pthread_detach(pthread_t tid);

功能:pthread_join()函數(shù)的替代函數(shù),可回收創(chuàng)建時detachstate屬性設(shè)置為PTHREAD_CREATE_JOINABLE的線程的存儲空間。該函數(shù)不會阻塞父線程。pthread_join()函數(shù)用于只是應(yīng)用程序在線程tid終止時回收其存儲空間。如果tid尚未終止,pthread_detach()不會終止該線程。當(dāng)然pthread_detach(pthread_self())也是可以得

頭文件:#include <pthread.h> pthread非linux系統(tǒng)的默認庫, 需手動鏈接-線程庫 -lpthread

參數(shù):tid:線程標(biāo)識符

返回值:pthread_detach() 在調(diào)用成功完成之后返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果檢測到以下任一情況,pthread_detach()將失敗并返回相應(yīng)的值。

EINVAL:tid是分離線程

ESRCH:tid不是當(dāng)前進程中有效的為分離線

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自:Youtherhttps://www.cnblogs.com/youtherhome/archive/201...
    njukay閱讀 1,721評論 0 52
  • 也是最近看YOLOV3的源碼的時候接觸到這里,demo()函數(shù)里是用到多線程編程的。我一開始是把線程這里是略掉的,...
    和藹的zhxing閱讀 629評論 0 5
  • 線程 在傳統(tǒng)操作系統(tǒng)中,每個進程有一個地址空間和一個控制線程。事實上這幾乎就是進程的定義。不過經(jīng)常存在在同一個地址...
    伊恩的道歉閱讀 2,373評論 0 6
  • 線程 線程的概念 典型的UNIX進程可以看成只有一個控制線程:一個進程在同一時刻只做一件事。有了多個控制線程后,在...
    ColdWave閱讀 1,589評論 0 0
  • 線程基礎(chǔ) 線程是進程的一個執(zhí)行單元,執(zhí)行一段程序片段,線程共享全局變量;線程的查看可以使用命令或者文件來進行查看;...
    秋風(fēng)弄影閱讀 806評論 0 0

友情鏈接更多精彩內(nèi)容