《UNIX環境高階程式設計》十七高階程序間通訊讀書筆記

2021-12-29 20:10:35 字數 3965 閱讀 9764

unix域套接字用於在同一臺計算機上執行的程序之間的通訊。

unix域套接字提供流和資料報兩種介面。unix域資料報服務是可靠的,既不會丟失報文也不會傳遞出錯。

使用socketpair函式來建立一對無命名的、相互連線的unix域套接字。

#include

int socketpair(int domain,int type,int protocol,int sockfd[2]);

//若成功,返回0;若出錯,返回-1

一對相互連線的unix域套接字可以起到全雙工管道的作用:兩端對讀和寫開放。將其稱為fd管道。

雖然socketpair函式能建立一對相互連線的套接字,但是每乙個套接字都沒有名字,無關程序不能使用它們。

unix域套接字的位址由sockaddr_un結構表示。在linux 3.2.0中,sockaddr_un結構在標頭檔案

struct sockaddr_un;sockaddr_un結構的sun_path成員包含乙個路徑名。當我們將乙個位址繫結到乙個unix域套接字時,系統會用該路徑名建立乙個s_issock型別的檔案。該檔案僅用於向客戶程序告示套接字名字。該檔案無法開啟,也不能由應用程式用於通訊。

如果我們試圖繫結同一位址時,該檔案已經存在,那麼bing請求會失敗。當關閉套接字時,並不自動刪除該檔案,所以必須確保在應用程式推出前,對該檔案執行解除鏈結操作。

確定socklen_t的方法:

size=offsetof(struct sockaddr_un,sun_path)+strlen(un.sun_path

伺服器程序可以使用標準bind、listen和accept函式,為客戶程序安排乙個唯一unix域連線。客戶程序使用connect與伺服器程序聯絡。在伺服器程序接受了connect請求後,在伺服器程序和客戶程序之間就存在了唯一連線。

我們將開發3個函式,使用這些函式可以在執行於同一臺計算機上點的兩個無關程序之間穿點唯一連線:

#include "apue.h"

int serv_listen(const char *name);

//若成功,返回要監聽的檔案描述符;若出錯,返回負值

int serv_accept(int listenfd,uid_t *uidptr);

//若成功,返回新檔案描述符;若出錯,返回負值

int cli_conn(const char *name);

//若成功,返回檔案描述符;若出錯,返回負值

伺服器程序可以呼叫serv_listen函式宣告它要在乙個眾所周知的名字(檔案系統中的某個路徑名)上監聽客戶程序的連線請求。serv_listen函式的返回值是用於接受客戶程序連線請求的伺服器unix域套接字。

客戶程序呼叫cli_conn函式連線至伺服器程序。客戶程序指定的name引數必須與伺服器程序呼叫serv_listen函式時所用的名字相同。

在兩個程序之間傳送開啟檔案描述符的技術是非常有用的。因此可以對客戶程序-伺服器程序應用進行不同的設計。它使乙個程序(通常是伺服器程序)能夠處理開啟乙個檔案所要做的一切操作以及向呼叫程序送回乙個描述符,該描述符可被用於以後的所有i/o函式。涉及開啟檔案或裝置的所有細節對客戶程序而言都是透明的。

當乙個程序向另乙個程序傳送乙個開啟檔案描述符時,我們想讓傳送程序和接收程序共享同一檔案表項:

在技術上,我們是將指向乙個開啟檔案表項的指標從乙個程序傳送到另外乙個程序。該指標被分配存放在接收程序的第乙個可用描述符中。兩個程序共享同乙個開啟檔案表,這與fork之後的父程序和子程序共享開啟檔案表的情況完全相同。

#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使用fd代表的unix域套接字傳送描述符fd_to_send。send_err使用fd傳送errmsg以及後隨的status位元組。status的值應在-1~-255.

為了用unix域套接字交換檔案描述符,呼叫sendmsg和recvmsg函式。這兩個函式的引數中都有乙個指向maghdr結構的指標,該結構包含了所有關於要傳送或要接收的訊息的資訊:

struct msghdr;前兩個元素通常用於在網路連線上傳送資料報。msg_flags欄位包含了描述接收到的訊息的標誌。

兩個元素處理控制資訊的傳送和接收。msg_control欄位指向cmsghdr(控制資訊頭)結構,msg_controllen欄位包含控制資訊的位元組數。

struct cmsghdr ;為了傳送檔案描述符,將cmsg_len設定為cmsghdr結構的長度加乙個整型的長度(描述符的長度),cmg_level欄位設定為sol_socket,cmsg_type欄位設定為scm_rights,用以表明在傳送訪問權。訪問權僅能通過unix域套接字傳送。描述符緊隨cmsg_type欄位之後儲存,用cmsg_data巨集獲得該整型量的指標。

#include

unsigned char *cmsg_data(struct cmsghdr *cp);

//返回乙個指標,指向與cmsghdr結構相關聯的資料

struct cmsghdr *cmsg_firsthdr(struct msghdr *mp);

//返回乙個指標,指向與msghdr結構相關聯的第乙個cmsghdr結構;若無這樣的結構,返回null

struct cmsghdr *cmsg_nxthdr(sturct msghdr *mp,

struct cmsghdr *cp);

//返回乙個指標,指向與msghdr結構相關聯的下乙個cmsghdr結構,該msghdr結構給出了當前的cmsghdr結構;若當前cmsghdr結構已是最後乙個,返回null

unsigned int cmsg_len(unsigned int nbytes);

//返回為nbytes長的資料物件分配的長度。

回憶serv_accept函式確定呼叫者身份的步驟。如果核心能夠把呼叫者的證書在呼叫accept之後返回給呼叫處會更好。

在linux中,將證書作為ucred結構傳送:

struct ucred ;注:需要在傳輸前初始化這個結構。

#include

int getopt(int argc,char *const ar**,const char *options);

extern int optind,opterr,optopt;

extern char *optarg;

若所有選項被處理完,返回-1;否則,返回下乙個選項字元。

引數argc和ar**與傳入main函式的一樣。options引數是乙個包含該命令支援的選項字元的字串。如果乙個選項字元後面接了乙個冒號,則表示該選項需要引數;否則,該選項不需要額外引數。

函式getopt一般用在迴圈體內,迴圈直到getopt返回-1時退出。每次迭代中,getopt會返回下乙個選項。

當遇到無效的選項時,getopt返回乙個問題標記而不是這個字元。如果選項缺少引數,getopt也會返回乙個問題標記,但如果選項字串的第乙個字元是冒號,getopt會直接返回冒號。而特殊的「–」格式則會導致getopt**停止處理選項**並返回-1。這允許使用者傳遞以「-」開頭但不是選項的引數。

getopt引數支援以下4個外部變數:

unix環境高階程式設計

unix 日曆時間 自1970 年1 月1 日00 00 00 以來的國際標準時間 utc 程序時間 cpu 時間 時鐘時間 程序執行時間的總量。使用者cpu 時間 執行使用者指令時間量。系統cpu 時間 執行核心所經歷時間。命令 time 第三章至第七章 原子操作 任何乙個要求多於1 個函式呼叫的...

unix環境高階程式設計

檔案描述符file descriptor通常是乙個小的非負整數,核心用以標識乙個特定程序正在訪問的檔案。當核心開啟乙個現有檔案或建立乙個新檔案時,它都返回乙個檔案描述符。在讀寫檔案時,可以私用這個檔案描述符。按管理,每當執行乙個新程式時,所有的shell都為其開啟了3個標準檔案描述符 標準輸入,標準...

UNIX環境高階程式設計

本書是被譽為unix程式設計 聖經 的advanced programming in the unix environment一書的更新版。在本書第1版出版後的十幾年中,unix行業已經有了巨大的變化,特別是影響unix程式設計介面的有關標準變化很大。本書在保持了前一版風格的基礎上,根據最新的標準對...