QNX之編寫資源管理器(九)

QNX相關(guān)歷史文章:

Multithreaded Resource Managers

這篇文章主要描述多線程來實(shí)現(xiàn)資源管理器童番。

1. Multithreaded resource manager example

先來看個(gè)例子:

#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>

/*
 *  define THREAD_POOL_PARAM_T such that we can avoid a compiler
 *  warning when we use the dispatch_*() functions below
 */
#define THREAD_POOL_PARAM_T dispatch_context_t

#include <sys/iofunc.h>
#include <sys/dispatch.h>

static resmgr_connect_funcs_t    connect_funcs;
static resmgr_io_funcs_t         io_funcs;
static iofunc_attr_t             attr;

main(int argc, char **argv)
{
    /* declare variables we'll be using */
    thread_pool_attr_t   pool_attr;
    resmgr_attr_t        resmgr_attr;
    dispatch_t           *dpp;
    thread_pool_t        *tpp;
    dispatch_context_t   *ctp;
    int                  id;

    /* initialize dispatch interface */
    if((dpp = dispatch_create()) == NULL) {
        fprintf(stderr,
                "%s: Unable to allocate dispatch handle.\n",
                argv[0]);
        return EXIT_FAILURE;
    }

    /* initialize resource manager attributes */
    memset(&resmgr_attr, 0, sizeof resmgr_attr);
    resmgr_attr.nparts_max = 1;
    resmgr_attr.msg_max_size = 2048;

    /* initialize functions for handling messages */
    iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs, 
                     _RESMGR_IO_NFUNCS, &io_funcs);

    /* initialize attribute structure used by the device */
    iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);

    /* attach our device name */
    id = resmgr_attach(
            dpp,            /* dispatch handle        */
            &resmgr_attr,   /* resource manager attrs */
            "/dev/sample",  /* device name            */
            _FTYPE_ANY,     /* open type              */
            0,              /* flags                  */
            &connect_funcs, /* connect routines       */
            &io_funcs,      /* I/O routines           */
            &attr);         /* handle                 */
    if(id == -1) {
        fprintf(stderr, "%s: Unable to attach name.\n", argv[0]);
        return EXIT_FAILURE;
    }

    /* initialize thread pool attributes */
    memset(&pool_attr, 0, sizeof pool_attr);
    pool_attr.handle = dpp;
    pool_attr.context_alloc = dispatch_context_alloc;
    pool_attr.block_func = dispatch_block;
    pool_attr.unblock_func = dispatch_unblock;
    pool_attr.handler_func = dispatch_handler;
    pool_attr.context_free = dispatch_context_free;
    pool_attr.lo_water = 2;
    pool_attr.hi_water = 4;
    pool_attr.increment = 1;
    pool_attr.maximum = 50;

    /* allocate a thread pool handle */
    if((tpp = thread_pool_create(&pool_attr, 
                                 POOL_FLAG_EXIT_SELF)) == NULL) {
        fprintf(stderr, "%s: Unable to initialize thread pool.\n",
                argv[0]);
        return EXIT_FAILURE;
    }

    /* start the threads, will not return */
    thread_pool_start(tpp);
}

線程池屬性pool_attr控制線程池的各個(gè)方面娜睛,比如新線程啟動(dòng)或終止時(shí)調(diào)用哪些函數(shù)羔沙、工作線程的總數(shù)筹误、最小數(shù)量等等磺送。

2. Thread pool attributes

_thread_pool_attr結(jié)構(gòu)如下:

typedef struct _thread_pool_attr {
  THREAD_POOL_HANDLE_T  *handle;
  THREAD_POOL_PARAM_T   *(*block_func)(THREAD_POOL_PARAM_T *ctp);
  void                  (*unblock_func)(THREAD_POOL_PARAM_T *ctp);
  int                   (*handler_func)(THREAD_POOL_PARAM_T *ctp);
  THREAD_POOL_PARAM_T   *(*context_alloc)(
                            THREAD_POOL_HANDLE_T *handle);
  void                  (*context_free)(THREAD_POOL_PARAM_T *ctp);
  pthread_attr_t        *attr;
  unsigned short        lo_water;
  unsigned short        increment;
  unsigned short        hi_water;
  unsigned short        maximum;
  unsigned              reserved[8];
} thread_pool_attr_t;

填充這個(gè)數(shù)據(jù)結(jié)構(gòu)中的函數(shù)代虾,可以是dispatch layer的函數(shù)(比如 dispatch_block()...)歉摧,也可以是resmgr layer的函數(shù)(比如 resmgr_block()...)艇肴,也可以是自己實(shí)現(xiàn)的函數(shù)腔呜。

如果不使用resmgr layer函數(shù),則必須將THREAD_POOL_PARAM_T定義為某種上下文結(jié)構(gòu)再悼,以便庫(kù)在各種函數(shù)間傳遞核畴。默認(rèn)情況下,它被定義為resmgr_context_t冲九,但由于這個(gè)示例使用的dispatch layer谤草,因此需要定義成dispatch_context_t。需要在include之前定義莺奸,因?yàn)轭^文件引用了THREAD_POOL_PARAM_T丑孩。

上邊結(jié)構(gòu)告訴資源管理器如何處理多線程。在開發(fā)過程中灭贷,在設(shè)計(jì)資源管理器時(shí)應(yīng)該考慮到多個(gè)線程温学,在測(cè)試期間,為了方便調(diào)試甚疟,可能只有一個(gè)線程在運(yùn)行仗岖,在確保資源管理器基本功能穩(wěn)定后,則需要嘗試使用多個(gè)線程來運(yùn)行調(diào)試览妖。

  • lo_water轧拄,阻塞線程的最小數(shù)量
  • increment,每次要?jiǎng)?chuàng)建的數(shù)量黄痪,以達(dá)到lo_water
  • hi_water紧帕,阻塞線程的最大數(shù)量
  • maximum,任何時(shí)候創(chuàng)建線程的最大數(shù)量

maximum值應(yīng)該確保始終有一個(gè)處于接收阻塞狀態(tài)的線程桅打,如果處于最大線程數(shù)是嗜,那么客戶端將阻塞,直到空閑線程準(zhǔn)備好接收數(shù)據(jù)為止挺尾。為increment指定的值將減少驅(qū)動(dòng)程序需要?jiǎng)?chuàng)建線程的次數(shù)鹅搪。明智的做法可能是錯(cuò)誤的創(chuàng)建更多的線程,而不是一直創(chuàng)建/銷毀它們遭铺。通過填充lo_water參數(shù)丽柿,可以隨時(shí)在MsgReceive()上確定希望接收阻塞的線程數(shù)。如果接收阻塞的線程少于lo_water線程魂挂,那么increment參數(shù)指定一次應(yīng)該創(chuàng)建多少個(gè)線程甫题,這樣至少lo_water線程的數(shù)量會(huì)再次被接收阻塞。一旦線程完成了處理涂召,將返回到block函數(shù)坠非。hi_water變量指定接收阻塞線程數(shù)量的上限,一旦達(dá)到這個(gè)限制果正,線程將自我銷毀炎码,以確保接收阻塞的線程數(shù)量不會(huì)超過hi_water盟迟。為了防止線程數(shù)量無限制的增加,maximum參數(shù)限制了同時(shí)運(yùn)行線程的最大值潦闲。
當(dāng)資源管理器創(chuàng)建線程時(shí)攒菠,可以通過thread_stack_size來指定堆棧的大小,如果想要指定堆棧的大小歉闰,優(yōu)先級(jí)等辖众,可以填充由pthread_attr_t類型指針指向的pool_attr.attr結(jié)構(gòu)。

thread_pool_attr_t結(jié)構(gòu)中新娜,還包含了幾個(gè)函數(shù)指針:

  • block_func()赵辕,當(dāng)需要阻塞等待某些消息時(shí)調(diào)用;
  • handler_func()概龄,當(dāng)接收到消息解除阻塞后調(diào)用还惠,在這個(gè)函數(shù)中對(duì)消息進(jìn)行處理;
  • context_alloc()私杜,新線程創(chuàng)建時(shí)調(diào)用蚕键,新線程使用這個(gè)上下文來工作;
  • context_free()衰粹,當(dāng)線程退出時(shí)锣光,釋放這個(gè)上下文;
  • unblock_func()铝耻,當(dāng)關(guān)閉線程池或改變運(yùn)行線程的數(shù)量時(shí)誊爹,調(diào)用這個(gè)函數(shù);

3. Thread pool functions

資源管理器庫(kù)提供了幾個(gè)線程池的函數(shù):

  • thread_pool_create()瓢捉,初始化線程池上下文频丘,返回一個(gè)線程池的handle,用于啟動(dòng)線程池泡态;
  • thread_pool_start()搂漠,啟動(dòng)線程池,這個(gè)函數(shù)可能返回某弦,也可能不返回桐汤,取決于thread_pool_create()的傳入flags
  • thread_pool_destroy()靶壮,銷毀線程池怔毛;
  • thread_pool_control(),控制線程的數(shù)量腾降;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末馆截,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜡娶,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件映穗,死亡現(xiàn)場(chǎng)離奇詭異窖张,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蚁滋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門宿接,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辕录,你說我怎么就攤上這事睦霎。” “怎么了走诞?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵副女,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蚣旱,道長(zhǎng)碑幅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任塞绿,我火速辦了婚禮沟涨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘异吻。我一直安慰自己裹赴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布诀浪。 她就那樣靜靜地躺著棋返,像睡著了一般。 火紅的嫁衣襯著肌膚如雪笋妥。 梳的紋絲不亂的頭發(fā)上懊昨,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音春宣,去河邊找鬼酵颁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛月帝,可吹牛的內(nèi)容都是我干的躏惋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嚷辅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼簿姨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤扁位,失蹤者是張志新(化名)和其女友劉穎准潭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體域仇,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刑然,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暇务。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泼掠。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垦细,靈堂內(nèi)的尸體忽然破棺而出择镇,到底是詐尸還是另有隱情,我是刑警寧澤括改,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布腻豌,位于F島的核電站,受9級(jí)特大地震影響叹谁,放射性物質(zhì)發(fā)生泄漏饲梭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一焰檩、第九天 我趴在偏房一處隱蔽的房頂上張望憔涉。 院中可真熱鬧,春花似錦析苫、人聲如沸兜叨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)国旷。三九已至,卻和暖如春茫死,著一層夾襖步出監(jiān)牢的瞬間跪但,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工峦萎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屡久,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓爱榔,卻偏偏與公主長(zhǎng)得像被环,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子详幽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一 昨天約上好友走路筛欢,勤快的她浸锨,已經(jīng)在體育中心太極館開練好幾天了。說到要上班了版姑,她莫名苦惱柱搜,晚上開始睡不著覺了。 ...
    丁若木閱讀 457評(píng)論 2 12
  • 頓感剥险,是這樣一種神奇的特性冯凹,不會(huì)因?yàn)閯e人責(zé)罵而內(nèi)心愧疚或者煎熬,不會(huì)因?yàn)樗速澝莱闯埃臍g呼雀躍,帶我撐過一些很難熬...
    擊空留影閱讀 662評(píng)論 0 0