日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux系统编程----15(线程与进程函数之间的对比,线程属性及其函数,线程属性控制流程,线程使用注意事项,线程库)

發布時間:2023/11/30 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux系统编程----15(线程与进程函数之间的对比,线程属性及其函数,线程属性控制流程,线程使用注意事项,线程库) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

對比

進程 線程 fork pthread_create exit (10) pthread_exit (void *) wait (int *) pthread_join (,void **)阻塞 kill pthread_cancel ();必須到取消點(檢查點):系統調用 man 7 pthreads getpid pthread_self 命名空間pthread_detach:分離,好處:自動清理pcb

什么類型作為返回值,回收就用哪個類型的地址

線程屬性

linux 下線程的屬性是可以根據實際項目需要,進行設置,之前我們討論的線程都是采用 線程的默認屬性,默認屬性已經可以解決絕大多數開發時遇到的問題。
如我們對程序的性能提出更高的要求那么需 要設置線程屬性,比如可以通過設置線程棧的大小來降低內存的使用,增加最大線程個數。

主要結構體成員:

  • 線程分離狀態
  • 線程棧大小(默認8M平均分配)
  • 線程棧警戒緩沖區大小(位于棧末尾) 為了防止線程溢出
  • 線程屬性說明

  • 屬性值不能直接設置,須使用相關函數進行操作,初始化的函數為 pthread_attr_init,這個函數必須在 pthread_create 函數之前調用。之后須用 pthread_attr_destroy 函數來釋放資源。
  • 線程屬性主要包括如下屬性:**作用域(scope)、棧尺寸(stacksize)、棧地址(stackaddress)、優先級(priority)、 分離的狀態(detachedstate)、調度策略和參數(schedulingpolicyandparameters)。**默認的屬性為非綁定、非分離、 缺省的堆棧、與父進程同樣級別的優先級。
  • 線程屬性控制流程

    線程屬性初始化

    注意:應先初始化線程屬性,再 pthread_create 創建線程

  • 初始化線程屬性
    int pthread_attr_init(pthread_attr_t *attr); 成功:0;失敗:錯誤號
  • 銷毀線程屬性所占用的資源
    int pthread_attr_destroy(pthread_attr_t *attr); 成功:0;失敗:錯誤號
  • 線程的分離狀態

    線程的分離狀態決定一個線程以什么樣的方式來終止自己。

  • 非分離狀態:線程的默認屬性是非分離狀態,這種情況下,原有的線程等待創建的線程結束。只有當 pthread_join() 函數返回時,創建的線程才算終止,才能釋放自己占用的系統資源。
  • 分離狀態:分離線程沒有被其他的線程所等待,自己運行結束了,線程也就終止了,馬上釋放系統資源。應該 根據自己的需要,選擇適當的分離狀態。
  • 線程分離狀態的函數:
    設置線程屬性,分離 or 非分離 int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);
    獲取線程屬性,分離 or 非分離 int pthread_attr_getdetachstate (pthread_attr_t *attr,int *detachstate);

    參數: attr:已初始化的線程屬性detachstate: PTHREAD_CREATE_DETACHED(分離線程) PTHREAD_CREATE_JOINABLE(非分離線程)
    示例1:
    #include<unistd.h> #include<stdio.h> #include<stdlib.h> #include<pthread.h> #include<string.h>void *thrd_func(void *arg) {pthread_exit((void *)77); }int main(void) {pthread_t tid;int ret;pthread_attr_t attr;ret = pthread_attr_init(&attr);if(ret != 0){ fprintf(stderr,"pthread_init error: %s\n",strerror(ret));exit(1);} pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);ret = pthread_create(&tid,&attr,thrd_func,NULL); if(ret != 0){ fprintf(stderr,"pthread_create error: %s\n",strerror(ret));exit(1);} ret = pthread_join(tid,NULL);printf("---------join ret = %d\n",ret);pthread_exit((void *)1); }

    示例2
    #include<stdio.h> #include<unistd.h> #include<string.h> #include<pthread.h>void *tfn(void *arg) {int n=3;while(n--){printf("thread count %d\n",n);sleep(1);}return (void *)1; }int main(void) {pthread_t tid;void *tret;int err;#if 1pthread_attr_t attr; //通過線程屬性類設置游離態pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);pthread_create(&tid,&attr,tfn,NULL);#elsepthread_create(&tid,NULL,tfn,NULL);pthread_detach(tid); //讓線程分離 ----自動退出,無系統殘留資源 #endifwhile(1){err = pthread_join(tid,&tret);printf("---------err= %d\n",err);if(err != 0)fprintf(stderr,"thread error: %s\n",strerror(err));elsefprintf(stderr,"thread exit code %d\n",(int)tret);sleep(1);}return 0; }

    注意事項

  • 如果設置一個線程為分離線程,而這個線程運行又非???#xff0c;它很可能在 pthread_create 函數返回之前就終止了,它終止以后就可能將線程號和系統資源移交給其他的線程使用,這樣調用 pthread_create 的線程就得到了錯誤的線程號。
  • 要避免這種情況可以采取一定的同步措施,最簡單的方法之一是可以在被創建的線 程里調用 pthread_cond_timedwait 函數,讓這個線程等待一會兒,留出足夠的時間讓函數 pthread_create 返回。
  • 設 置一段等待時間,是在多線程編程里常用的方法。但是注意不要使用諸如 wait()之類的函數,它們是使整個進程睡
    眠,并不能解決線程同步的問題。
  • 線程的棧大小

    當系統中有很多線程時,可能需要減小每個線程棧的默認大小,防止進程的地址空間不夠用,當線程調用的函 數會分配很大的局部變量或者函數調用層次很深時,可能需要增大線程棧的默認大小。
    函數 pthread_attr_getstacksize 和 pthread_attr_setstacksize 提供設置。

  • int pthread_attr_setstacksize(pthread_attr_t *attr,size_t stacksize); 成功:0;失敗:錯誤號
  • int pthread_attr_getstacksize(pthread_attr_t *attr,size_t *stacksize); 成功:0;失敗:錯誤號
  • 參數: attr:指向一個線程屬性的指針 stacksize:返回線程的堆棧大小

  • 默認線程棧均分8M空間

    查看一個進程最多能創建多少個線程
    #include<stdio.h> #include<string.h> #include<stdlib.h> #include<pthread.h>void *tfn(void *arg) {while(1)sleep(1); }int main(void) {pthread_t tid;int ret,count = 1;for(;;){ret = pthread_create(&tid,NULL,tfn,NULL);if(ret != 0){ printf("%s\n",strerror(ret)); break;} printf("-----------%d\n",++count);} return 0; }


    我的是能創建4094個線程

    線程屬性控制示例
    #include<stdio.h> #include<unistd.h> #include<pthread.h> #include<string.h> #include<stdlib.h>#define SIZE 0x100000void *th_fun(void * arg) {while(1);sleep(1); }int main(void) {pthread_t tid;int err, detachstate,i=1;pthread_attr_t attr;size_t stacksize;void *stackaddr;pthread_attr_init(&attr);pthread_attr_getstack(&attr,&stackaddr,&stacksize);pthread_attr_getdetachstate(&attr,&detachstate);if(detachstate == PTHREAD_CREATE_DETACHED)//默認是分離態printf("thread detached\n");else if(detachstate == PTHREAD_CREATE_JOINABLE)//默認非分離printf("thread join\n");elseprintf("thread un known\n");//設置線程分離pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);while(1){//在堆上申請內存,指定線程棧的起始地址和大小stackaddr = malloc(SIZE);if(stackaddr == NULL){perror("malloc");exit(1);}stacksize = SIZE;pthread_attr_setstack(&attr,stackaddr,stacksize);//借助線程的屬性,修 改線程??臻g大小err = pthread_create(&tid,&attr,th_fun,NULL);if(err != 0){printf("%s\n",strerror(err));exit(1);}printf("%d\n",i++);//i表示循環創建多少次}pthread_attr_destroy(&attr);return 0; }

    NPTL(線程庫)

  • 查看當前 pthread 庫版本 getconfGNU_LIBPTHREAD_VERSION
  • NPTL 實現機制(POSIX),NativePOSIXThreadLibrary
  • 使用線程庫時 gcc 指定 –lpthread
  • 線程使用注意事項

  • 主線程退出其他線程不退出,主線程應調用 pthread_exit
  • 避免僵尸線程
    pthread_join
    pthread_detach
    pthread_create 指定分離屬性
    被 join 線程可能在 join 函數返回前就釋放完自己的所有內存資源,所以不應當返回被回收線程棧中的值;
  • malloc 和 mmap 申請的內存可以被其他線程釋放
  • 應避免在多線程模型中調用 fork 除非,馬上 exec,子進程中只有調用 fork 的線程存在,其他線程在子進程 中均 pthread_exit
  • 信號的復雜語義很難和多線程共存,應避免在多線程引入信號機制
  • 總結

    以上是生活随笔為你收集整理的Linux系统编程----15(线程与进程函数之间的对比,线程属性及其函数,线程属性控制流程,线程使用注意事项,线程库)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。