mozilla的IO實作是分層的,本質上和BIO是一樣的,隻是寫法不同罷了,最上層,mozilla封裝了一個結構體:
struct PRFileDesc {
const PRIOMethods *methods; //本層的IO函數的實作
PRFilePrivate *secret;
PRFileDesc *lower, *higher; //上下兩層,如此所有的層次可以三個三個連成連結清單
void (PR_CALLBACK *dtor)(PRFileDesc *fd);
PRDescIdentity identity; //辨別
};
關于mozilla對分層io描述符的實作請參考nsprpub/pr/src/io/prio.c和nsprpub/pr/src/io/prlayer.c,特别值得一提的是最具有代表性的push操作:
PR_IMPLEMENT(PRStatus) PR_PushIOLayer(PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd)
{
PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id);
if (stack == insert) { //插入在目前IO棧的頂端
PRFileDesc copy = *stack;
*stack = *fd;
*fd = copy;
fd->higher = stack;
stack->lower = fd;
stack->higher = NULL;
} else { //插入在目前IO棧的任意位置
fd->lower = insert;
fd->higher = insert->higher;
insert->higher->lower = fd;
insert->higher = fd;
}
return PR_SUCCESS;
}
和OpenSSL的BIO_push是十分類似的,隻是BIO_push隻能在頂端push,是真正的push,而mozilla的實作命名為insert倒是更好。類似的,PR_CreateIOLayerStub和OpenSSL的BIO_new很類似,都是初始化一個新的“要插入”的io描述符,BIO_next在mozilla中直接通過結構體引用,即fd->lower,BIO中的BIO_METHOD實作了本層的io政策,而mozilla的prio實作中的PRIOMethods起着同樣的作用。
通過使用PRFileDesc以及prio所提供的衆接口,你可以将一系列的io例程堆積在一起,形成一個io棧,這就是分層的思想。分層的IO可以很友善的加入任何自定義的過濾政策和資料加工政策。突然想到,windows作業系統的drivers目錄下有一個叫做tcpip.sys的檔案,而unix在/dev目錄下亦有一個ip,tcp檔案。
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271799