日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php框架 > 框架設(shè)計(jì) > pjlib線(xiàn)程實(shí)現(xiàn)簡(jiǎn)析

pjlib線(xiàn)程實(shí)現(xiàn)簡(jiǎn)析

來(lái)源:程序員人生   發(fā)布時(shí)間:2015-08-28 08:53:13 閱讀次數(shù):5722次
本篇主要講授pjlib關(guān)于線(xiàn)程的實(shí)現(xiàn)方式

轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/lhl_blog/article/details/44063229

系統(tǒng)環(huán)境:
1. Ubuntu14.04 TLS 內(nèi)核3.13.0⑷5-generi
2. gcc 4.8.2

3. glibc 2.19


開(kāi)始之前需要講授兩個(gè)概念:

1.線(xiàn)程棧

    參考nono的csdn博文http://blog.csdn.net/dog250/article/details/7704898,其對(duì)linux的進(jìn)程和線(xiàn)程棧進(jìn)行了較為詳細(xì)的介紹.個(gè)人認(rèn)為比較重要的就是
    linux glibc所實(shí)現(xiàn)的線(xiàn)程棧為不能動(dòng)態(tài)增長(zhǎng)的,這就很值得注意了,如果線(xiàn)程中定義使用比較大的數(shù)據(jù)結(jié)構(gòu)就會(huì)致使線(xiàn)程棧溢出,而線(xiàn)程棧是在進(jìn)程的堆中分
    配的內(nèi)存,從而城門(mén)失火,殃及池魚(yú),這樣1旦線(xiàn)程棧溢出就會(huì)間接破壞進(jìn)程地址空間,從而致使很難調(diào)試的bug(可能致使內(nèi)存段毛病).因此,有效的管理線(xiàn)程
    棧在多線(xiàn)程編程中就成了比較重要的問(wèn)題.或許,有的人會(huì)說(shuō),我在進(jìn)行多線(xiàn)程編程時(shí),對(duì)線(xiàn)程棧也沒(méi)有進(jìn)行過(guò)量干預(yù)啊,也沒(méi)有出現(xiàn)過(guò)甚么問(wèn)題啊? 這類(lèi)認(rèn)識(shí)
    實(shí)際上是存在問(wèn)題的, 正所謂欠下的債早晚是要還的,是時(shí)候未到.

    至于表面上沒(méi)有出現(xiàn)問(wèn)題,主要緣由以下:

    1.*NIX系統(tǒng)在創(chuàng)建線(xiàn)程時(shí),如果沒(méi)有指定線(xiàn)程棧的大小,系統(tǒng)會(huì)創(chuàng)建1個(gè)默許大小的棧(8M),我們1般不會(huì)使用如此'大'的自動(dòng)變量,但是如果線(xiàn)程定義了大量
    的自動(dòng)變量,例如,定義了char array[8*1024*1024]的數(shù)組,不出意外程序會(huì)出現(xiàn)段毛病,示例代碼以下:


#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* threadfunc(void* args)
{
    //char c = '1';
    //printf("c = %c ", c);
    char *str1 = (char *)malloc(8*1024*1024);
    char *str2 = (char *)malloc(8*1024*1024);
    char array[8*1024*1024 - 1024*10] = {0};
}

int main(void)
{
    pthread_t pid;
    size_t stack_size;
    pthread_attr_t attr;

    int rc = pthread_create(&pid, NULL, threadfunc, NULL);
    if(rc != 0) {
        printf("create thread failed ");
    }

    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr, &stack_size); 
    stack_size /= 1024 * 1024;
    printf("default thread stacksize = %dMB ", stack_size);
    pthread_join(pid, NULL);
    return 0;
}

2.線(xiàn)程TLS

  線(xiàn)程TLS(thread locak store),線(xiàn)程私有數(shù)據(jù)是存儲(chǔ)和查詢(xún)與某個(gè)線(xiàn)程相干的數(shù)據(jù)的1種機(jī)制.把這類(lèi)數(shù)據(jù)稱(chēng)為線(xiàn)程私有數(shù)據(jù)或線(xiàn)程特定數(shù)據(jù)的緣由為, 希望每
  個(gè)線(xiàn)程可以獨(dú)立的訪(fǎng)問(wèn)數(shù)據(jù)副本,而不用擔(dān)心與其他線(xiàn)程的同步訪(fǎng)問(wèn)問(wèn)題. 典型的利用為每一個(gè)線(xiàn)程具有自己的errno值, 各個(gè)線(xiàn)程之間的errno值互不影響.這就像
  身份證定義空間好比系統(tǒng)的進(jìn)程空間,每一個(gè)獨(dú)立的人好比1個(gè)單獨(dú)的線(xiàn)程,每一個(gè)線(xiàn)程都有1個(gè)身份證號(hào),這個(gè)身份證號(hào)就是我們的TLS,而且我們之間的身份證號(hào)
  不會(huì)相互影響,固然這個(gè)比喻有些不恰當(dāng),理論上身份證號(hào)是1成不變的.

3.pjlib線(xiàn)程實(shí)現(xiàn)

3.1 安全的線(xiàn)程棧保護(hù)機(jī)制

struct pj_thread_t
{
    char            obj_name[PJ_MAX_OBJ_NAME];
    pthread_t       thread;//linux 線(xiàn)程id
    pj_thread_proc  *proc;//線(xiàn)程處理函數(shù)
    void            *arg;//線(xiàn)程處理函數(shù)參數(shù)
    pj_uint32_t     signature1;//標(biāo)簽1,具體作用未知
    pj_uint32_t     signature2;//標(biāo)簽2
    pj_mutex_t      *suspended_mutex;//摹擬線(xiàn)程掛起動(dòng)作
    //如果啟用了線(xiàn)程棧相干的檢查處理,則定義下面的成員變量:
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
    pj_uint32_t     stk_size;//線(xiàn)程棧大小j
    pj_uint32_t     stk_max_usage;//已使用的線(xiàn)程棧大小
    char            *stk_start;//線(xiàn)程棧的起始地址
    const char      *caller_file;//用于記錄調(diào)用線(xiàn)程棧檢測(cè)函數(shù)確當(dāng)前位置
    int             caller_line;
#endif
};

pjlib線(xiàn)程描寫(xiě)符明肯定義了線(xiàn)程棧相干的元素, 通過(guò)這些元素, pjlib線(xiàn)程可以基本實(shí)現(xiàn)安全的線(xiàn)程棧使用.下面介紹pjlib線(xiàn)程棧的使用機(jī)制的實(shí)現(xiàn)方式.

3.1.1 線(xiàn)程棧初始化    

     pjlib的pj_thread_create實(shí)現(xiàn)pjlib線(xiàn)程的創(chuàng)建,其中函數(shù)的stack_size為線(xiàn)程棧大小參數(shù),下面的代碼只保存pj_thread_create函數(shù)的參數(shù)和線(xiàn)程棧相干的內(nèi)容:
/*
 * pj_thread_create(...)
 */


PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool,
        const char *thread_name,
        pj_thread_proc *proc,
        void *arg,
        pj_size_t stack_size,
        unsigned flags,
        pj_thread_t **ptr_thread)
{
    ...
#if PJ_HAS_THREADS
    PJ_CHECK_STACK();

    /* Set default stack size */
    if (stack_size == 0)
        stack_size = PJ_THREAD_DEFAULT_STACK_SIZE;
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
    rec->stk_size = stack_size;
    rec->stk_max_usage = 0;
#endif

//第1種方式:
#if defined(PJ_THREAD_SET_STACK_SIZE) && PJ_THREAD_SET_STACK_SIZE!=0
    /* Set thread's stack size */
    rc = pthread_attr_setstacksize(&thread_attr, stack_size);
    if (rc != 0)
        return PJ_RETURN_OS_ERROR(rc);
#endif /* PJ_THREAD_SET_STACK_SIZE */

//第2種方式:
#if defined(PJ_THREAD_ALLOCATE_STACK) && PJ_THREAD_ALLOCATE_STACK!=0
    /* Allocate memory for the stack */
    stack_addr = pj_pool_alloc(pool, stack_size);
    PJ_ASSERT_RETURN(stack_addr, PJ_ENOMEM);

    rc = pthread_attr_setstackaddr(&thread_attr, stack_addr);
    if (rc != 0)
        return PJ_RETURN_OS_ERROR(rc);
#endif /* PJ_THREAD_ALLOCATE_STACK */
    ...
    /* Create the thread. */
    rec->proc = proc;
    rec->arg = arg;
    rc = pthread_create( &rec->thread, &thread_attr, &thread_main, rec);
    if (rc != 0) {
        return PJ_RETURN_OS_ERROR(rc);
    }
    ...
}

static void *thread_main(void *param)
{
    pj_thread_t *rec = (pj_thread_t*)param;
    void *result;
    pj_status_t rc;

#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
    rec->stk_start = (char*)&rec;
#endif
....

}
     pjlib支持兩種線(xiàn)程棧創(chuàng)建方式,1.使用系統(tǒng)默許線(xiàn)程棧大小直接創(chuàng)建. 2.動(dòng)態(tài)申請(qǐng)堆內(nèi)存,然后將堆內(nèi)存地址作為線(xiàn)程棧的首地址.創(chuàng)建完線(xiàn)程棧以后,pjlib在
     thread_main中對(duì)線(xiàn)程棧的起始地址進(jìn)行了初始化.

3.1.2 線(xiàn)程棧保護(hù)機(jī)制 

    pjlib線(xiàn)程通過(guò)在每一個(gè)線(xiàn)程函數(shù)中調(diào)用PJ_CHECK_STACK()宏實(shí)現(xiàn)線(xiàn)程棧的保護(hù)機(jī)制,線(xiàn)程函數(shù)履行履行之前首先通過(guò)PJ_CHECK_STACK()監(jiān)測(cè)當(dāng)前線(xiàn)程棧狀態(tài),如果
    線(xiàn)程棧空間的使用率到達(dá)規(guī)定的警界值就會(huì)立即觸發(fā)assert斷言提示線(xiàn)程STACK OVERFLOW!,并退出.反之,PJ_CHECK_STACK()會(huì)重新更新當(dāng)前線(xiàn)程棧的使用率.下
    面為PJ_CHECK_STACK()(pj_thread_check_stack)的實(shí)現(xiàn):
/*
 * pj_thread_check_stack()
 * Implementation for PJ_CHECK_STACK()
 */
PJ_DEF(void) pj_thread_check_stack(const char *file, int line)
{
    char stk_ptr;
    pj_uint32_t usage;
    pj_thread_t *thread = pj_thread_this();

    /*計(jì)算當(dāng)前線(xiàn)程棧的使用率*/
    usage = (&stk_ptr > thread->stk_start) ? &stk_ptr - thread->stk_start :
        thread->stk_start - &stk_ptr;

    /*如果線(xiàn)程棧的使用率超過(guò)警界值,立即觸發(fā)斷言*/
    pj_assert("STACK OVERFLOW!! " && (usage <= thread->stk_size - 128));

    /*重新統(tǒng)計(jì)線(xiàn)程棧使用率*/
    if (usage > thread->stk_max_usage) {
        thread->stk_max_usage = usage;
        thread->caller_file = file;
        thread->caller_line = line;
    }
}
    
    PJ_CHECK_STACK()1般在線(xiàn)程函數(shù)定義完局部變量時(shí)調(diào)用,這樣就能夠?qū)tack overflow提早預(yù)警,從而減少大量的調(diào)試時(shí)間.

3.2 pjlib TLS

    pjlib線(xiàn)程基于TLS機(jī)制實(shí)現(xiàn)本地線(xiàn)程描寫(xiě)符的存儲(chǔ),所有pjlib線(xiàn)程或外部線(xiàn)程(linux原生線(xiàn)程)都必須使用pj_thread_register將自己的描寫(xiě)符存儲(chǔ)到TLS中,
    當(dāng)調(diào)用pjlib庫(kù)函數(shù)時(shí),庫(kù)函數(shù)1般都會(huì)檢測(cè)本地線(xiàn)程是不是注冊(cè)過(guò),即是不是調(diào)用過(guò)pthread_setspecific()注冊(cè)線(xiàn)程TLS,否則pjlib庫(kù)函數(shù)不能被正常使用,只有
    這樣才能光明正大的使用pjlib函數(shù).    

    pjlib這樣做的理由可能為:
    1.每一個(gè)pjlib線(xiàn)程都有1個(gè)線(xiàn)程描寫(xiě)符pj_thread_t,每一個(gè)描寫(xiě)符中保存的內(nèi)容各不相同,我們可以通過(guò)線(xiàn)程TLS將不同線(xiàn)程的描寫(xiě)符實(shí)現(xiàn)統(tǒng)1管理,就像errno.
    2.方便線(xiàn)程調(diào)試,通過(guò)TLS可以方便的獲得本地線(xiàn)程相干的所有信息,我們通過(guò)打印或在線(xiàn)調(diào)試都可以方便的跟蹤當(dāng)前調(diào)用函數(shù)的線(xiàn)程狀態(tài).    
    3. ... ... 

3.3 pjlib線(xiàn)程調(diào)度策略

    pjlib線(xiàn)程封裝了linux系統(tǒng)提供的幾種線(xiàn)程調(diào)度策略,SCHED_FIFO,SCHED_RR,SCHED_OTHER,沒(méi)有特別的設(shè)置.
生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線(xiàn)----------------------------
分享到:
------分隔線(xiàn)----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 玖玖在线 | 欧美77777| 成人国产在线观看 | 国产精品久久久久久久久免费软件 | 亚洲精品久久久蜜桃 | 成人18视频 | 国产视频a | 午夜精品999 | 九一网站在线观看 | 一级黄色网 | 欧美激情视频在线观看 | www.99re.| 久久精品电影 | 92久久精品| av中文字幕在线播放 | 久久久久久久一区 | 日韩欧美三区 | 一级特黄录像免费播放全99 | 国产嫩草一区二区三区在线观看 | 国产精品99久久久久 | 亚久久 | 日韩一区二区久久 | 一区二区免费 | 久久成人在线视频 | 亚洲 中文 欧美 日韩 在线观看 | 国产一区自拍视频 | 免费黄网站在线观看 | 91福利视频合集 | 国产精品久久久久婷婷二区次 | 亚洲乱码国产乱码精品精98午夜 | 午夜激情久久久 | 日韩欧美高清一区二区 | 99精品一区二区三区 | 精品天堂| 黄色片网战 | 二区影院| 91久久精品一区二区 | 嫩草视频91 | 麻豆一级| 国产成人av一区二区三区 | 欧美日韩大片 |