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

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

Filesystem Resource Managers

這篇文章主要描述文件系統(tǒng)資源管理器。

1. Considerations for filesystem resource managers

由于文件系統(tǒng)資源管理器可能會收到很長的路徑名,因此它必須要能夠正確地解析和處理路徑的每個部分。
比如,一個資源管理器注冊了掛載點(diǎn)/mount,當(dāng)用戶輸入:ls -l /mount/home時, 其中/mount/home是設(shè)備中的一個路徑,
那么ls會做以下事情:

d = opendir("/mount/home");
while (...) {
    dirent = readdir(d);
    ...
}

2. Taking over more than one device

當(dāng)資源管理器需要處理多個設(shè)備時,可以對每個設(shè)備名調(diào)用resmgr_attach()接口進(jìn)行注冊,此外每個設(shè)備還需要唯一的屬性結(jié)構(gòu),當(dāng)像chmod()等函數(shù)被調(diào)用時,便可對特定設(shè)備的屬性進(jìn)行修改。
示例代碼如下:

/* 
 *  MOD [1]:  allocate multiple attribute structures,
 *            and fill in a names array (convenience)
 */

#define NumDevices  2
iofunc_attr_t     sample_attrs [NumDevices];
char              *names [NumDevices] =
{
    "/dev/sample1",
    "/dev/sample2"
};

main ()
{
    ...
    /*
     *  MOD [2]:  fill in the attribute structure for each device 
     *           and call resmgr_attach for each device           
     */
    for (i = 0; i < NumDevices; i++) {
        iofunc_attr_init (&sample_attrs [i],
                          S_IFCHR | 0666, NULL, NULL);
        pathID = resmgr_attach (dpp, &resmgr_attr, name[i],
                                 _FTYPE_ANY, 0,
                                 &my_connect_funcs,
                                 &my_io_funcs,
                                 &sample_attrs [i]);
    }
    ...
}                            

在這個代碼中,增加了屬性結(jié)構(gòu)的數(shù)組,并且多次調(diào)用了resmgr_attach()接口,其他地方不需要修改。io_readio_write處理函數(shù)不需要改動,iofunc layer默認(rèn)處理函數(shù)會去處理多種設(shè)備的情況。

3. Handling directories

之前的例子路徑名都是在/dev目錄下,資源管理器不會限制只能在某個路徑下,并可以處理任何數(shù)量的路徑名,一個實際的限制在于當(dāng)數(shù)量越多的時候,可能面臨內(nèi)存不足以及查找速度慢等問題。
當(dāng)路徑名數(shù)量很多時,一個最直接的辦法就是使用路徑名前綴,比如:

  • CD-ROM文件系統(tǒng),可以使用前綴/cdrom,當(dāng)對這個路徑下的名字操作時,都會去處理CD-ROM設(shè)備;
  • 一個處理壓縮文件的文件系統(tǒng),可以使用前綴/uncompressed
  • 網(wǎng)絡(luò)文件系統(tǒng)可以使用/mount/flipper路徑名來顯示遠(yuǎn)程機(jī)器,當(dāng)訪問這個路徑時,就像訪問本地機(jī)器;

上邊這些例子的特點(diǎn)是都實現(xiàn)了文件系統(tǒng),文件系統(tǒng)資源管理器與設(shè)備資源管理器在以下幾個關(guān)鍵領(lǐng)域有區(qū)別:

  • resmgr_attach()參數(shù)中的_RESMGR_FLAG_DIR位會通知庫,資源管理器會在掛載點(diǎn)路徑或掛載點(diǎn)路徑下接受匹配;
  • _IO_CONNECT邏輯必須根據(jù)數(shù)據(jù)權(quán)限和訪問權(quán)限來檢查路徑名的各個部分,它還必須確保在訪問特定文件名時綁定了適當(dāng)?shù)膶傩裕?/li>
  • _IO_READ邏輯必須返回路徑名指定的“文件”或“路徑”數(shù)據(jù);

3.1 Matching at or below a mountpoint

在使用resmgr_attach()函數(shù)時,傳入的flags參數(shù)為_RESMGR_FLAG_DIR時,表明允許在指定的掛載點(diǎn)路徑或該路徑之下進(jìn)行路徑名解析。如果flags參數(shù)為0,表明使用默認(rèn)值。

3.2 The _IO_OPEN message for filesystems

假設(shè)注冊了一個掛載點(diǎn)/sample_fsys,如下:

pathID = resmgr_attach
             (dpp,
             &resmgr_attr,
             "/sample_fsys",    /* mountpoint */
            _FTYPE_ANY,
             _RESMGR_FLAG_DIR,   /* it's a directory */
             &connect_funcs,
             &io_funcs,
             &attr);

當(dāng)客戶端調(diào)用如下代碼:

fopen ("/sample_fsys/spud", "r");

資源管理器會收到_IO_CONNECT消息,并且調(diào)用io_read處理函數(shù)。_IO_CONNECT消息的數(shù)據(jù)結(jié)構(gòu)如下:

struct _io_connect {
    unsigned short  type;
    unsigned short  subtype;     /* _IO_CONNECT_*              */
    unsigned long   file_type;   /* _FTYPE_* in sys/ftype.h    */
    unsigned short  reply_max;
    unsigned short  entry_max;
    unsigned long   key;
    unsigned long   handle;
    unsigned long   ioflag;      /* O_* in fcntl.h, _IO_FLAG_* */
    unsigned long   mode;        /* S_IF* in sys/stat.h        */
    unsigned short  sflag;       /* SH_* in share.h            */
    unsigned short  access;      /* S_I in sys/stat.h          */
    unsigned short  zero;
    unsigned short  path_len;
    unsigned char   eflag;       /* _IO_CONNECT_EFLAG_*        */
    unsigned char   extra_type;  /* _IO_EXTRA_*                */
    unsigned short  extra_len;
    unsigned char   path[1];     /* path_len, null, extra_len  */
};

其中ioflat, mode, sflag, access表明資源是如何打開的。參數(shù)path_len表明路徑名占多少字節(jié),path放置實際的路徑名。注意,出現(xiàn)的路徑名是spud,而不是/sample_fsys/spud,這是因為消息只包含相對于掛載點(diǎn)的路徑名。還要注意的是,路徑名中不會有相對路徑(., ..)部分,也不會冗余的斜杠(/),這些都會在消息發(fā)送到資源管理器時被解析和刪除。

當(dāng)編寫文件系統(tǒng)資源管理器時,在處理路徑名時可能會有一些復(fù)雜的情況,為了驗證訪問,我們需要分解傳遞的路徑名,并對每個部分進(jìn)行檢查??梢允褂?code>strtok()等來分解路徑名字符串,然后調(diào)用iofunc_check_access()來進(jìn)行訪問驗證。驗證名稱之后發(fā)生的綁定要求處理的每個路徑都有自己的屬性結(jié)構(gòu),如果將錯誤的屬性綁定到所提供的路徑名,將會導(dǎo)致意外的行為。

3.3 Returning directory entries from _IO_READ

當(dāng)_IO_READ處理函數(shù)被調(diào)用后,可能需要返回文件(如果S_ISDIR(ocb->attr->mode)為false),也可能需要返回目錄(如果S_ISDIR(ocb->attr->mode)為true)。
對于將目錄返回給客戶端,存在一些約束,返回的不是一個字節(jié)流,返回的是幾個struct dirent的數(shù)據(jù)結(jié)構(gòu),dirent結(jié)構(gòu)必須4字節(jié)對齊。數(shù)據(jù)結(jié)構(gòu)如下:

struct dirent {
#if _FILE_OFFSET_BITS - 0 == 64
    ino_t           d_ino;          /* File serial number. */
    off_t           d_offset;
#elif !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS == 32
#if defined(__LITTLEENDIAN__)
    ino_t           d_ino;          /* File serial number. */
    ino_t           d_ino_hi;
    off_t           d_offset;
    off_t           d_offset_hi;
#elif defined(__BIGENDIAN__)
    ino_t           d_ino_hi;
    ino_t           d_ino;          /* File serial number. */
    off_t           d_offset_hi;
    off_t           d_offset;
#else
 #error endian not configured for system
#endif
#else
 #error _FILE_OFFSET_BITS value is unsupported
#endif
    _Int16t             d_reclen;
    _Int16t             d_namelen;
    char                d_name[1];
};

d_ino成員包含一個掛載點(diǎn)唯一的文件序列號。這個序列號通常用于各種磁盤檢查程序中。在有些文件系統(tǒng)中,d_offset用于標(biāo)識目錄條目本身,而在其他情況下,它是下一個目錄項的偏移量。d_reclen成員包含此目錄項的大小和任何其他相關(guān)信息。d_namelen參數(shù)指示d_name參數(shù)的大小,d_name保存該目錄項的實際名稱。
dirent結(jié)構(gòu)中僅包含名稱的前四個字節(jié)的空間,_IO_READ處理程序需要返回一個更大的結(jié)構(gòu),包含名字和dirent,如下:

struct {
    struct dirent ent;
    char namebuf[NAME_MAX + 1 + offsetof(struct dirent, d_name) -
                 sizeof( struct dirent)];
} entry

或者定義成聯(lián)合體:

union {
    struct dirent ent;
    char filler[ offsetof( struct dirent, dname ) + NAME_MAX + 1];
} entry;

在我們的io_read處理程序中,需要生成許多struct dirent條目,并返回給客戶端。如果在資源管理器中維護(hù)了目錄項緩存,那么構(gòu)造一組IOVs來指向這些項即可。如果沒有緩存的話,則必須手動將目錄項組裝到緩沖區(qū)中,然后返回指向該緩沖區(qū)的IOV。

3.3.1 Returning information associated with a directory structure

除了返回_IO_READ消息中的struct dirent外,還可以返回struct stat,盡管這個可以提高效率,但是struct stat完全是可選的,如果不返回struct stat的話,客戶端就必須通過stat()/lstat()來獲取該信息。

客戶端可以通過將消息的xtype成員設(shè)置成_IO_XFLAG_DIR_EXTRA_HINT,以便向文件系統(tǒng)發(fā)送提示以返回額外的信息,但文件系統(tǒng)不保證這樣做。如果資源管理器提供信息,則必須將其放入到struct dirent_extra_stat中,定義如下:

struct dirent_extra_stat {
    _Uint16t            d_datalen;
    _Uint16t            d_type;
    _Uint32t            d_reserved;
    struct stat         d_stat;
};

資源管理器必須將d_type設(shè)置為_DTYPE_LSTAT_DTYPE_STAT,這取決于它是否解析符號鏈接。比如:

if(msg->i.xtype & _IO_XFLAG_DIR_EXTRA_HINT) { 
    struct dirent_extra_stat    extra;
    extra.d_datalen = sizeof extra.d_stat;
    extra.d_type = _DTYPE_LSTAT;
    extra.d_reserved = 0;
    iofunc_stat(ctp, &attr, &extra.d_stat);
    ...
}

每個目錄項后都有一個dirent_extra_stat

Returning the optional struct dirent_extra_stat along with the struct dirent entry can improve efficiency

dirent結(jié)構(gòu)必須在4字節(jié)邊界上對齊,dirent_extra_stat結(jié)構(gòu)必須在8字節(jié)邊界上對齊,d_reclen成員必須包含這兩個結(jié)構(gòu)的大小,包含路徑名和對齊所需的任何空間。最多不超過7字節(jié)的對齊填充。

客戶端必須調(diào)用_DEXTRA_*()宏來檢查額外的數(shù)據(jù),如果檢查失敗,則需要顯示調(diào)用lstat()stat()。比如,ls -l檢查額外的_DTYPE_LSTAT信息,如果不存在,ls調(diào)用lstat()ls -L檢查額外的_DTYPE_STAT信息,如果不存在,ls調(diào)用stat()。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • QNX相關(guān)歷史文章:QNX簡介QNX Neutrino微內(nèi)核QNX IPC機(jī)制QNX進(jìn)程管理器QNX資源管理器QN...
    Loyen閱讀 2,480評論 0 0
  • QNX相關(guān)歷史文章:QNX簡介QNX Neutrino微內(nèi)核QNX IPC機(jī)制QNX進(jìn)程管理器QNX資源管理器QN...
    Loyen閱讀 6,916評論 0 12
  • QNX相關(guān)歷史文章:QNX簡介QNX Neutrino微內(nèi)核QNX IPC機(jī)制QNX進(jìn)程管理器QNX資源管理器QN...
    Loyen閱讀 3,550評論 0 0
  • QNX相關(guān)歷史文章:QNX簡介QNX Neutrino微內(nèi)核QNX IPC機(jī)制QNX進(jìn)程管理器 1. Introd...
    Loyen閱讀 4,593評論 1 4
  • QNX相關(guān)歷史文章:QNX簡介QNX Neutrino微內(nèi)核QNX IPC機(jī)制QNX進(jìn)程管理器QNX資源管理器QN...
    Loyen閱讀 7,159評論 0 1

友情鏈接更多精彩內(nèi)容