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

QNX相關歷史文章:

Fleshing Out the Skeleton

在講完大體框架后痛阻,這篇文章將涉及到更多細節(jié):消息類型;資源管理器屬性锄禽;添加功能赢赊;安全事項等唤蔗。

1. Message types

在前文中也提到過窘拯,資源管理器需要處理兩類消息:

  • connect message底桂,連接消息
  • I/O message湖苞, IO消息

1.1 connect message

客戶端發(fā)出connect message來執(zhí)行基于路徑名的操作烹吵。當調用resmgr_attach()函數(shù)時碉熄,會將一個指針傳遞給resmgr_connect_funcs_t結構,該結構定義了一系列連接函數(shù):

typedef struct _resmgr_connect_funcs {

    unsigned nfuncs;

    int (*open)      (resmgr_context_t *ctp, io_open_t *msg,
                      RESMGR_HANDLE_T *handle, void *extra);

    int (*unlink)    (resmgr_context_t *ctp, io_unlink_t *msg,
                      RESMGR_HANDLE_T *handle, void *reserved);

    int (*rename)    (resmgr_context_t *ctp, io_rename_t *msg,
                      RESMGR_HANDLE_T *handle,
                      io_rename_extra_t *extra);

    int (*mknod)     (resmgr_context_t *ctp, io_mknod_t *msg,
                      RESMGR_HANDLE_T *handle, void *reserved);

    int (*readlink)  (resmgr_context_t *ctp, io_readlink_t *msg,
                      RESMGR_HANDLE_T *handle, void *reserved);

    int (*link)      (resmgr_context_t *ctp, io_link_t *msg,
                      RESMGR_HANDLE_T *handle,
                      io_link_extra_t *extra);

    int (*unblock)   (resmgr_context_t *ctp, io_pulse_t *msg,
                      RESMGR_HANDLE_T *handle, void *reserved);

    int (*mount)     (resmgr_context_t *ctp, io_mount_t *msg,
                      RESMGR_HANDLE_T *handle,
                      io_mount_extra_t *extra);
} resmgr_connect_funcs_t;

可以調用iofunc_func_init()接口來用默認的處理程序指針來初始化這個結構肋拔。自己也可以重寫某些接口锈津,進行覆蓋即可。
需要注意的是凉蜂,resmgr_attach()接口只是將函數(shù)指針拷貝到resmgr_connect_func_tresmgr_io_funcs_t結構中琼梆,而不是拷貝整個結構。需要分配這些結構窿吩,將它們聲明為靜態(tài)的或者全局變量茎杂。如果資源管理器用于具有不同處理程序的多個設備,則應該分開定義獨立的結構纫雁。
這些連接消息都有一個_IO_CONNECT類型煌往,此外還有子類型來進行分類,各個字段介紹如下:

  • nfuncs轧邪,結構中函數(shù)的個數(shù)刽脖,可用于擴展;
  • open忌愚,處理客戶端的open()/fopen()/sopen()等請求曲管,消息子類型包括_IO_CONNECT_COMBINE, _IO_CONNECT_COMBINE_CLOSE, _IO_CONNECT_OPEN等;
  • unlink菜循,處理客戶端unlink()請求翘地,消息子類型為_IO_CONNECT_UNLINK申尤;
  • rename,處理客戶端rename()請求衙耕,消息子類型為_IO_CONNECT_RENAME昧穿;
  • mknod,處理客戶端mkdir()/mkfifo()/mknod()請求橙喘,消息子類型為_IO_CONNECT_MKNOD时鸵;
  • readlink,處理客戶端readlink()請求厅瞎,消息子類型為_IO_CONNECT_READLINK饰潜;
  • link,處理客戶端link()請求和簸,消息子類型為_IO_CONNECT_LINK彭雾;
  • unlock,處理來自內核的請求锁保,以便在連接消息階段接觸對客戶端的阻塞薯酝;
  • mount,處理客戶端mount()請求爽柒,消息子類型為_IO_CONNECT_MOUNT吴菠;

1.2 I/O messages

I/O消息依賴于客戶端和資源管理器之間已有的綁定關系,比如當客戶端調用read()函數(shù)發(fā)送_IO_READ消息時浩村,需要先通過open()函數(shù)來與資源管理器建立綁定關系做葵,進而獲取到文件描述符。
regmgr_io_funcs_t結構體定義了I/O消息處理函數(shù):

typedef struct _resmgr_io_funcs {
    unsigned    nfuncs;
    int (*read)       (resmgr_context_t *ctp, io_read_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*write)      (resmgr_context_t *ctp, io_write_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*close_ocb)  (resmgr_context_t *ctp, void *reserved,
                       RESMGR_OCB_T *ocb);
    int (*stat)       (resmgr_context_t *ctp, io_stat_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*notify)     (resmgr_context_t *ctp, io_notify_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*devctl)     (resmgr_context_t *ctp, io_devctl_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*unblock)    (resmgr_context_t *ctp, io_pulse_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*pathconf)   (resmgr_context_t *ctp, io_pathconf_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*lseek)      (resmgr_context_t *ctp, io_lseek_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*chmod)      (resmgr_context_t *ctp, io_chmod_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*chown)      (resmgr_context_t *ctp, io_chown_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*utime)      (resmgr_context_t *ctp, io_utime_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*openfd)     (resmgr_context_t *ctp, io_openfd_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*fdinfo)     (resmgr_context_t *ctp, io_fdinfo_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*lock)       (resmgr_context_t *ctp, io_lock_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*space)      (resmgr_context_t *ctp, io_space_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*shutdown)   (resmgr_context_t *ctp, io_shutdown_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*mmap)       (resmgr_context_t *ctp, io_mmap_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*msg)        (resmgr_context_t *ctp, io_msg_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*reserved)   (resmgr_context_t *ctp, void *msg,
                       RESMGR_OCB_T *ocb);
    int (*dup)        (resmgr_context_t *ctp, io_dup_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*close_dup)  (resmgr_context_t *ctp, io_close_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*lock_ocb)   (resmgr_context_t *ctp, void *reserved,
                       RESMGR_OCB_T *ocb);
    int (*unlock_ocb) (resmgr_context_t *ctp, void *reserved,
                       RESMGR_OCB_T *ocb);
    int (*sync)       (resmgr_context_t *ctp, io_sync_t *msg,
                       RESMGR_OCB_T *ocb);
    int (*power)      (resmgr_context_t *ctp, io_power_t *msg,
                       RESMGR_OCB_T *ocb);
} resmgr_io_funcs_t;

這個結構的使用與resmgr_connect_funcs_t一樣心墅,對應到客戶端的不同請求酿矢,及消息類型。

1.3 Default message handling

由于資源管理器接收的大量消息處理的是一組公共的屬性怎燥,因此QNX提供了一個iofunc_*()共享庫棠涮,實現(xiàn)了一些默認的消息處理函數(shù)。目前實現(xiàn)的默認函數(shù)可用于處理客戶端的以下請求:

  • chmod()
  • chown()
  • close()
  • devctl()
  • fpathconf()
  • fseek()
  • fstat()
  • lockf()
  • lseek()
  • mmap()
  • open()
  • pathconf()
  • stat()
  • utime()

2. Setting resource manager attribute

除了定義connectI/O函數(shù)結構體之外刺覆,resmgr_attach()函數(shù)還需要用到resmgr_attr_t來指定資源管理器的屬性严肪。定義如下:

typedef struct _resmgr_attr {
    unsigned            flags;
    unsigned            nparts_max;
    unsigned            msg_max_size;
    int                 (*other_func)(resmgr_context_t *,
                                      void *msg);
    unsigned            reserved[4];    
} resmgr_attr_t;

各個成員介紹如下:

  1. flags
    可用于修改資源管理器接口的行為,可以將其設置為0谦屑,或者是以下不同狀態(tài)的組合:
  • RESMGR_FLAG_ATTACH_LOCAL驳糯,設置資源管理器,不向procnto注冊路徑氢橙,可以向資源管理器通道發(fā)送消息酝枢;
  • RESMGR_FLAG_ATTACH_OTHERFUNC,該結構中的other_func成員指向一個用于未處理I/O消息的函數(shù)悍手;
  • RESMGR_FLAG_CROSS_ENDIAN帘睦,服務器支持跨端處理袍患,可以在服務器端做必要的轉換,客戶端不需要做任何事情竣付;
  • RESMGR_FLAG_NO_DEFAULT诡延,未實現(xiàn);
  • RESMGR_FLAG_RCM古胆,在處理請求時自動采取客戶端的資源約束模式肆良;
  1. nparts_max
    分配給IOV數(shù)組的組件數(shù)量。

  2. msg_max_size
    消息緩沖的大小逸绎。
    這些成員在實現(xiàn)自己的處理函數(shù)時很重要惹恃。

  3. other_func
    other_func可用于指定一個例程,在資源管理器接收到不能理解的I/O消息時調用棺牧。要使用這個成員巫糙,需要在flag字段里置上RESMGR_FLAG_ATTACH_OTHERFUNC。如果other_func成員設置成NULL的話颊乘,資源管理器在收到不能理解的消息時曲秉,便會返回ENOSYS錯誤給客戶端。
    對于非I/O消息類型時疲牵,需要使用message_attach()接口來將消息綁定到dispatch handle上。

3. Ways of adding functionality to the resource manager

3.1 Using the default functions

下邊是一個使用自己的io_open處理程序的示例:

main (int argc, char **argv)
{
    …

    /* install all of the default functions */
    iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
                      _RESMGR_IO_NFUNCS, &io_funcs);

    /* take over the open function */
    connect_funcs.open = io_open;
    …
}

int
io_open (resmgr_context_t *ctp, io_open_t *msg, 
         RESMGR_HANDLE_T *handle, void *extra)
{
    return (iofunc_open_default (ctp, msg, handle, extra));
}

上述的代碼只是一個增量步驟榆鼠,可以允許在調用默認處理函數(shù)之前或者之后執(zhí)行某些操作纲爸,比如可以實現(xiàn)如下代碼:

/* example of doing something before */

extern int accepting_opens_now;

int
io_open (resmgr_context_t *ctp, io_open_t *msg,
         RESMGR_HANDLE_T *handle, void *extra)
{
    if (!accepting_opens_now) {
        return (EBUSY);
    }

    /* 
     *  at this point, we're okay to let the open happen,
     *  so let the default function do the "work".
     */

    return (iofunc_open_default (ctp, msg, handle, extra));
}

或者:

/* example of doing something after */

int
io_open (resmgr_context_t *ctp, io_open_t *msg,
         RESMGR_HANDLE_T *handle, void *extra)
{
    int     sts;

    /* 
     * have the default function do the checking 
     * and the work for us
     */

    sts = iofunc_open_default (ctp, msg, handle, extra);

    /* 
     *  if the default function says it's okay to let the open
     *  happen, we want to log the request
     */

    if (sts == EOK) {
        log_open_request (ctp, msg);
    }
    return (sts);
}

這種方法的優(yōu)勢是,只需要很少的工作就可以添加到標準的默認POSIX處理程序中妆够。

3.2 Using the helper functions

在很多默認處理函數(shù)中识啦,都調用到了幫助函數(shù),比如下邊的iofunc_chmod_default()iofunc_stat_default()

int
iofunc_chmod_default (resmgr_context_t *ctp, io_chmod_t *msg,
                      iofunc_ocb_t *ocb)
{
    return (iofunc_chmod (ctp, msg, ocb, ocb -> attr));
}

int
iofunc_stat_default (resmgr_context_t *ctp, io_stat_t *msg,
                     iofunc_ocb_t *ocb)
{
    iofunc_time_update (ocb -> attr);
    iofunc_stat (ocb -> attr, &msg -> o);
    return (_RESMGR_PTR (ctp, &msg -> o,
                         sizeof (msg -> o)));
}

在上邊的代碼中分別都調用到了iofunc_chmod()神妹、iofunc_time_update()颓哮、iofunc_stat()等幫助函數(shù)。

更復雜的case如下:

int
iofunc_open_default (resmgr_context_t *ctp, io_open_t *msg,
                     iofunc_attr_t *attr, void *extra)
{
    int     status;

    iofunc_attr_lock (attr);

    if ((status = iofunc_open (ctp, msg, attr, 0, 0)) != EOK) {
        iofunc_attr_unlock (attr);
        return (status);
    }

    if ((status = iofunc_ocb_attach (ctp, msg, 0, attr, 0)) 
        != EOK) {
        iofunc_attr_unlock (attr);
        return (status);
    }

    iofunc_attr_unlock (attr);
    return (EOK);
}

調用了以下幫助函數(shù):

  • iofunc_attr_lock()接口鸵荠,獲取鎖冕茅,用于互斥訪問屬性結構;
  • iofunc_open()蛹找,進行權限驗證姨伤;
  • iofunc_ocb_attach(),綁定OCB結構庸疾;
  • iofunc_attr_unlock()乍楚,釋放鎖;

3.3 Writing the entire function yourself

有時候默認的處理函數(shù)對特定的資源管理器來說沒有用處届慈,可以自己實現(xiàn)處理函數(shù)徒溪,在這些實現(xiàn)的處理函數(shù)中忿偷,可以去調用幫助函數(shù),比如iofunc_read_verify()臊泌。

4. Security

資源管理器通常是一個特權進程鲤桥,因此需要小心,防止客戶端迫使它耗盡資源或損耗系統(tǒng)缺虐。在設計資源管理器時芜壁,應該考慮以下幾點:

  • 管理路徑名空間中資源管理器條目的權限,可以將權限指定為iofunc_attr_init()的參數(shù)高氮;
  • 資源管理器通常需要運行在root權限慧妄,以便能與路徑名空間綁定,但是更好的方式是運行在非root權限剪芍,而使用procmgr_ability()去獲取特權的能力塞淹。
  • 如果資源管理器不是一個沒有資源約束閾值的關鍵進程,它可以簡單的運行在約束模式下罪裹,而如果是一個關鍵進程饱普,應該保持PROCMGR_AID_RCONSTRAINT能力,需要確保受約束的客戶端不使用它來分配超過當前閾值的資源状共。
  • 對客戶端的能力進行檢查套耕,通常可以調用ConnectClientInfoAble()iofunc_client_info_able()來檢查峡继。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末冯袍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子碾牌,更是在濱河造成了極大的恐慌康愤,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舶吗,死亡現(xiàn)場離奇詭異征冷,居然都是意外死亡,警方通過查閱死者的電腦和手機誓琼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門检激,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腹侣,你說我怎么就攤上這事呵扛。” “怎么了筐带?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵今穿,是天一觀的道長。 經常有香客問我伦籍,道長蓝晒,這世上最難降的妖魔是什么腮出? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮芝薇,結果婚禮上胚嘲,老公的妹妹穿的比我還像新娘。我一直安慰自己洛二,他們只是感情好馋劈,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晾嘶,像睡著了一般妓雾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上垒迂,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天械姻,我揣著相機與錄音,去河邊找鬼机断。 笑死楷拳,一個胖子當著我的面吹牛,可吹牛的內容都是我干的吏奸。 我是一名探鬼主播欢揖,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奋蔚!你這毒婦竟也來了她混?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤旺拉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后棵磷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛾狗,經...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年仪媒,在試婚紗的時候發(fā)現(xiàn)自己被綠了沉桌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡算吩,死狀恐怖留凭,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情偎巢,我是刑警寧澤蔼夜,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站压昼,受9級特大地震影響求冷,放射性物質發(fā)生泄漏瘤运。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一匠题、第九天 我趴在偏房一處隱蔽的房頂上張望拯坟。 院中可真熱鬧,春花似錦韭山、人聲如沸郁季。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梦裂。三九已至,卻和暖如春续搀,著一層夾襖步出監(jiān)牢的瞬間塞琼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工禁舷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留彪杉,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓牵咙,卻偏偏與公主長得像派近,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子洁桌,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內容