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

主要結構體成員:

  1. 線程分離狀態
  2. 線程棧大小(默認8M平均分配)
  3. 線程棧警戒緩沖區大小(位于棧末尾) 為了防止線程溢出

線程屬性說明

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

線程屬性控制流程

線程屬性初始化

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

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

線程的分離狀態

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

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

線程分離狀態的函數:
設置線程屬性,分離 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;
}              

在這里插入圖片描述

注意事項

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

線程的棧大小

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

  1. int pthread_attr_setstacksize(pthread_attr_t *attr,size_t stacksize); 成功:0;失敗:錯誤號
  2. int pthread_attr_getstacksize(pthread_attr_t *attr,size_t *stacksize); 成功:0;失敗:錯誤號
  3. 參數: 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);//借助線程的屬性,修
改線程棧空間大小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(線程庫)

  1. 查看當前 pthread 庫版本 getconfGNU_LIBPTHREAD_VERSION
  2. NPTL 實現機制(POSIX),NativePOSIXThreadLibrary
  3. 使用線程庫時 gcc 指定 –lpthread

線程使用注意事項

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383222.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383222.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383222.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

內核雙向循環鏈表

#include <string.h>#include <stdio.h>#include <stdlib.h>#include<malloc.h>#include <arpa/inet.h>//鏈表頭結構struct list_head{struct list_head *next,*prev;};//真正實現鏈表插入操作void _list_add(struct list_head *nnew,struct lis…

Linux系統編程----16(線程同步,互斥量 mutex,互斥鎖的相關函數,死鎖,讀寫鎖)

同步概念 所謂同步&#xff0c;即同時起步&#xff0c;協調一致。不同的對象&#xff0c;對“同步”的理解方式略有不同。如&#xff0c;設備同步&#xff0c;是指在兩 個設備之間規定一個共同的時間參考&#xff1b;數據庫同步&#xff0c;是指讓兩個或多個數據庫內容保持一致…

轉移字符的轉換

使得網頁上不會顯示 \x0a\x0a \x0a \x0a \x0a \x0a 類似的字符static int te_escape_isDec(char *ptr, unsigned int len) { …

Linux系統編程---17(條件變量及其函數,生產者消費者條件變量模型,生產者與消費者模型(線程安全隊列),條件變量優點,信號量及其主要函數,信號量與條件變量的區別,)

條件變量 條件變量本身不是鎖&#xff01;但它也可以造成線程阻塞。通常與互斥鎖配合使用。給多線程提供一個會合的場所。 主要應用函數&#xff1a; pthread_cond_init 函數pthread_cond_destroy 函數pthread_cond_wait 函數pthread_cond_timedwait 函數pthread_cond_signa…

好友

http://blog.csdn.net/liangyuannao/article/details/8583139

Linux系統編程---18(線程池相關概念及其實現)

線程池 概念&#xff1a; 一堆線程任務隊列 作用 避免大量線程頻繁的創建/銷毀時間成本避免瞬間大量線程創建耗盡資源&#xff0c;程序崩潰危險 實現 創建固定數量的線程創建一個線程安全的任務隊列 一種線程使用模式。 線程過多會帶來調度開銷&#xff0c;進而影響緩…

設計模式--1(設計模式基礎,設計模式基本原則,設計模式分類)

設計模式基礎 模式 在一定環境中解決某一問題的方案&#xff0c;包括三個基本元素–問題&#xff0c;解決方案和環境。大白話&#xff1a;在一定環境下&#xff0c;用固定套路解決問題。 設計模式 是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使…

source insight 使用技巧

source insight 使用技巧 1 sourceinsight screen font 的默認字體是Verdana的&#xff0c;它是一直變寬字體。在Document style中可以將字體改為定寬的Courier2 document options->auto indent 去掉indent Open Brace和Indent Close Brace的效果: 繼上一段&#xff0c;在…

設計模式----2(簡單工廠模式的概念,簡單工廠模式的實現,簡單工廠模式的優缺點)

簡單工廠模式 簡單工廠模式的概念 簡單工廠模式屬于類的創建型模式,又叫做靜態工廠方法模式。通過專門定義一個類來負 責創建其他類的實例&#xff0c;被創建的實例通常都具有共同的父類。 具體分類 工廠&#xff08;Creator&#xff09;角色 簡單工廠模式的核心&#xff0…

Redis常見問題及其一些重點知識總結

1、什么是 Redis&#xff1f;簡述它的優缺點&#xff1f; Redis 的全稱是&#xff1a;Remote Dictionary.Server&#xff0c;本質上是一個 Key-Value 類型的內存數據庫&#xff0c;很像 memcached&#xff0c;整個數據庫統統加載在內存當中進行操作&#xff0c;定期通過異步操…

shell生成隨機文件名

1 #!/bin/bash 2 # tempfile-name.sh: 臨時文件名產生器 3 4 BASE_STRmcookie # 32-字符的 magic cookie. 5 POS11 # 字符串中隨便的一個位置. 6 LEN5 # 取得 $LEN 長度連續的字符串. 7 8 prefixtemp # 最終的一個臨時文…

設計模式---3(工廠方法模式的概念,工廠方法模式的實現,工廠方法模式和簡單工廠模式比較)

工廠方法模式 概念 工廠方法模式同樣屬于類的創建型模式又被稱為多態工廠模式 。 工廠方法模式的意義 定義一個創建產品對象的工廠接口&#xff0c;將實際創建工作推遲到子類當中。 核心工廠類不再負責產品的創建&#xff0c;這樣核心類成為一個抽象工廠角色&#xff0c;僅…

設計模式---4(抽象工廠模式的概念,產品組和產品等級的概念,抽象工廠模式的實現)

抽象工廠模式 抽象工廠模式的概念 抽象工廠模式是所有形態的工廠模式中最為抽象和最其一般性的。抽象工廠模式可以向 客戶端提供一個接口&#xff0c;使得客戶端在不必指定產品的具體類型的情況下&#xff0c;能夠創建多個產品 族的產品對象。 抽象工廠的角色及其職責 抽象工…

Win32項目關于MessageBox參數的詳細說明

函數功能&#xff1a;該函數創建、顯示、和操作一個消息框。消息框含有應用程序定義的消息和標題&#xff0c;加上預定義圖標與Push&#xff08;下按&#xff09;按鈕的任何組合。 函數原型&#xff1a;int MessageBox(HWND hWnd,LPCTSTR IpCaption,UINT…

w3af解析

1. w3af簡介 w3afis a Web Application Attack and Audit Framework.即Web應用攻擊和審計框架。w3af用python編寫&#xff0c;依賴的庫主要有2類&#xff0c;分別如下&#xff1a; <1> Core requirements: Python 2.6 fpconst-0.7.2&#xff1a;用于處理IEEE 754浮點…

1.c++中初始化列表和構造函數初始化的區別是什么?2.類的成員變量的初始化順序是按照聲明順序嗎?

初始化列表和構造函數初始化的區別是什么&#xff1f; 初始化和賦值對內置類型的成員沒有太大的區別&#xff0c;在成員初始化列表和構造函數體內進行&#xff0c;在性能和結果上都是一樣的。只有一些需要注意的事項 初始化列表一般情況如下&#xff1a; Date(int year, int …

設計模式---5(建造者模式的概念及其實現,建造者模式的角色與職責,建造者模式和工廠模式的區別)

建造者模式 建造者模式的概念 Builder 模式也叫建造者模式或者生成器模式&#xff0c;是由 GoF 提出的 23 種設計模式中的一種。 Builder 模式是一種對象創建型模式之一&#xff0c;用來隱藏復合對象的創建過程&#xff0c;它把復合對象的 創建過程加以抽象&#xff0c;通過子…

system阻塞SIGCHLD信號原因

system阻塞SIGCHLD信號原因 標簽&#xff1a; c 2014-11-08 11:58 198人閱讀 評論(0) 收藏 舉報 分類&#xff1a; linux編程&#xff08;1&#xff09; 代碼1&#xff1a;APUE10.18節的system函數源代碼 int system(const char *cmdstring) /* with appropriate signal ha…

設計模式6---(單例模式的概念及其實現(懶漢式和餓漢式),線程安全)

單例模式 單例模式的概念 單例模式是一種對象創建型模式&#xff0c;使用單例模式&#xff0c;可以保證為一個類只生成唯一的實例對象。也就是說&#xff0c;在整個程序空間中&#xff0c;該類只存在一個實例對象。 GoF 對單例模式的定義是&#xff1a;保證一個類、只有一個實…

C語言解析http請求表單內容

[1].[文件] cgi.h ~ 405B 下載(105) 跳至 [1] [2] [3] [4] [5] [6] [7] [8] ?123456789101112131415161718192021222324252627#ifndef CGI_H#define CGI_H#include <stdio.h>#include <string.h>#include <stdlib.h>typedef struct Node{char *…