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檔案。