這章屬於進階內容 內容比較簡略
1.基於STREAMS的管道
流管道是一個雙向(全雙工系統)管道。單個流管道就能向父、子進程提供雙向的資料流
1).命名的STREAMS管道
我們可以用fattach函數來在檔案系統給一個STREAMS管道一個名字
#include <stropts.h>int fattach(int filedes, const char *path);//成功返回0,錯誤返回-1。
path參數必須引用一個已有的檔案,調用進程必須擁有這個檔案,或有對它有寫的許可權,或使用超級使用者提高權限執行。
一個進程可以調用fdetach來撤消STREAMS檔案和檔案系統裡的名字之間的關聯關係。
#include <stropts.h>int fdetach(const cha *path);//成功返回0,錯誤返回-1。
在fdetach被調用後,任何通過開啟path而有STREAMS管道的訪問的進程將仍繼續訪問這個流,但是後續的path開啟會訪問在檔案系統裡的原始檔案。
2).唯一串連
在將一個STREAMS管道串連到檔案系統的一個名字之前,伺服器處理序可將connld模組推到要被附加的管道那端。這導致所示的配置。
2.Unix域通訊端
UNIX域通訊端被用來和同一機器上啟動並執行進程通訊。儘管網際網路域通訊端可以用作同樣的目的,然而UNIX域通訊端更高效。
可以使用面向網路的通訊端介面來使用它們,或者你可以使用socketpair函數然建立一對沒有名字的、串連的UNIX域通訊端。
#include <sys/socket.h>int socketpair(int domain, int type, int protocol, int sockfd[2]);//成功返回0,錯誤返回-1。
1).命名UNIX域通訊端
2).唯一串連
3.傳遞檔案描述符
下面三個函數可以發送和接收檔案描述符
#include "apue.h"int send_fd(int fd, int fd_to_send);int send_err(int fd, int status, const char *errmsg);//成功返回0,錯誤返回-1。int recv_fd(int fd, ssize_t (*userfunc)(int, const void *, size_t));//成功返迴文件描述符,錯誤返回負值。
當一個進程(通常是伺服器)希望將一個描述符傳送給另一個進程時,它調用send_fd或send_err。等待接收描述符的進程(客戶機)調用recv_fd。
send_fd經由fd代表的STREAM管道或UNIX域通訊端發送描述符fd_to_send
send_err 經由用fd發送errmsg和status位元組。status的值應在-1 ~-2 5 5之間
1).經由基於STREAMS的管道來傳遞檔案描述符
檔案描述符使用兩個ioctl命令經由STREAMS管道交換,這兩個命令是:I_SENDFD和I_RECVFD
2)經由UNIX域通訊端來傳遞檔案描述符
為了用UNIX域通訊端分頁檔描述符,我們調用sendmsg和recvmsg函數,涉及下面的函數和結構體(詳見UNP)
下面三個宏被用來存取控制資料,一個宏用來協助計算用於cmsg_len的值
#include <sys/socket.h>unsigned char *CMSG_DATA(struct cmsghdr *cp);//返回和cmsghdr結構體相關的資料的指標。struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *mp);//返回和msghdr結構體相關聯的第一個cmsghdr結構體的指標,或者沒有一個存在時返回NULL。struct cmsghdr *CMSG_NXTHDR(struct msghdr *mp, struct cmsghdr *cp);//給定當前cmsghdr結構體,返回和msghdr結構體相關聯的下一個cmsghdr結構體的指標,或我們已經在最後一個上時返回NULLunsigned int CMSG_LEN(unsigned int nbytes);//返回為nbytes大的資料對象分配的尺寸。
其中msghdr和cmsghdr結構體,這兩個結構體對資料傳送進行了控制
struct msghdr { void *msg_name; /* optional address */ socklen_t msg_namelen; /* address size in bytes */ struct iovec *msg_iov; /* array of I/O buffers */ int msg_iovlen; /* number of elements in array */ void *msg_control; /* ancillary data */ socklen_t msg_controllen; /* number of ancillary bytes */ int msg_flags; /* flags for received message */};struct cmsghdr { socklen_t cmsg_len; /* data byte count, including header */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by the actual control message data */};