熊偉++丁涵++羅云鋒
摘要:Netlink是Linux操作系統(tǒng)內(nèi)核空間與用戶空間最流行的進(jìn)程間通信機(jī)制之一,但目前在多線程程序中的使用還存在一些問題。介紹了Netlink相對于Linux其它傳統(tǒng)通信手段的優(yōu)點(diǎn),闡述了使用Netlink進(jìn)行用戶程序與內(nèi)核模塊通信的實(shí)現(xiàn)方法,分析了目前公開資料上Netlink線程并發(fā)支持機(jī)制存在的問題,并給出了支持多線程并發(fā)與消息異步處理的正確方法,最后在真實(shí)機(jī)器上進(jìn)行了驗(yàn)證。結(jié)果顯示,該方法能有效支持在多線程Linux應(yīng)用中使用Netlink進(jìn)行用戶態(tài)與內(nèi)核態(tài)通信。
關(guān)鍵詞:Linux;nelink;進(jìn)程間通信;多線程并發(fā);異步處理
DOIDOI:10.11907/rjdk.172576
中圖分類號:TP319文獻(xiàn)標(biāo)識碼:A文章編號:16727800(2017)010009905
0引言
Linux是當(dāng)今應(yīng)用最廣泛的操作系統(tǒng)之一,其兼容性好,能適應(yīng)從嵌入式設(shè)備、個人用戶終端到高性能服務(wù)器的不同硬件平臺,具有多任務(wù)與多用戶能力。Linux符合POSIX標(biāo)準(zhǔn),在GNU公共許可權(quán)限下可免費(fèi)獲得其內(nèi)核源代碼,同時還具備完整的軟件生態(tài)鏈,包含各種開發(fā)工具及第三方軟件庫,非常方便用戶開發(fā)定制自己的應(yīng)用。
Linux采用模塊化單內(nèi)核架構(gòu),支持內(nèi)核模塊動態(tài)加載與卸載,其系統(tǒng)地址空間結(jié)構(gòu)如圖1所示。Linux所有
圖1Linux操作系統(tǒng)結(jié)構(gòu)
內(nèi)核代碼可看作一個整體,運(yùn)行在一個獨(dú)立的地址空間中,通常被稱為內(nèi)核空間[1]。運(yùn)行于內(nèi)核空間的代碼不受任何限制,能夠自由地訪問任何有效地址以及直接進(jìn)行設(shè)備訪問。而用戶應(yīng)用運(yùn)行在內(nèi)核之上,其不能隨意占用系統(tǒng)資源與修改系統(tǒng)配置,從而確保系統(tǒng)安全性與穩(wěn)定性。
在日常應(yīng)用中,應(yīng)用程序通常包括上層用戶界面程序與底層內(nèi)核驅(qū)動模塊兩部分,用戶界面負(fù)責(zé)接收用戶輸入及顯示最終處理結(jié)果,內(nèi)核驅(qū)動則負(fù)責(zé)調(diào)用內(nèi)核處理用戶請求。因此內(nèi)核空間與用戶空間進(jìn)行通信的方法非常重要。
目前,Linux常用的內(nèi)核用戶通信機(jī)制有以下幾種[2]:
(1)設(shè)備驅(qū)動接口。設(shè)備節(jié)點(diǎn)位于/dev目錄下。設(shè)備驅(qū)動接口允許用戶訪問設(shè)備節(jié)點(diǎn)[3],利用copy_from_user()與copy_to_user()函數(shù),在用戶態(tài)與內(nèi)核態(tài)間拷貝數(shù)據(jù)。但是這兩個函數(shù)只支持阻塞式調(diào)用,不能在中斷中使用,而且只支持用戶程序主動進(jìn)行通信,通常用在硬件驅(qū)動中。
(2)Proc與sysfs文件系統(tǒng)。Proc與sysfs是虛擬文件系統(tǒng),用于顯示進(jìn)程、處理器、內(nèi)存、中斷等信息[4,5]。用戶可以通過讀寫這兩種文件系統(tǒng)與內(nèi)核進(jìn)行通信。其最大缺點(diǎn)是不支持基于事件的信號機(jī)制,數(shù)據(jù)傳輸大小也不能超過一個內(nèi)存頁,可擴(kuò)展性較差。
(3)內(nèi)存映射。/dev/mem是Linux系統(tǒng)中一種特殊的字符設(shè)備文件[6],應(yīng)用程序通過這個節(jié)點(diǎn),可以在內(nèi)核地址空間與用戶地址空間進(jìn)行映射,然后訪問映射后的內(nèi)存區(qū)域,實(shí)現(xiàn)用戶空間與內(nèi)核空間的通信。但是對內(nèi)核地址的誤操作將引起嚴(yán)重后果,導(dǎo)致系統(tǒng)崩潰。
(4)Netlink套接字。Netlink是一種面向數(shù)據(jù)報(bào)的消息系統(tǒng),目前在Linux內(nèi)核中有非常多應(yīng)用可用于通信,包括路由、IPSEC、防火墻、netfilter日志等[710]。Netlink具有以下特點(diǎn):消息具有較強(qiáng)的擴(kuò)展能力,用戶可以自定義消息格式,且提供了基于事件的信號機(jī)制,允許大數(shù)據(jù)傳輸;支持全雙工傳輸,允許內(nèi)核主動發(fā)起傳輸通信;支持單播與組播兩種通信方式[11]。
如上所述,目前在Linux系統(tǒng)內(nèi)核空間與用戶空間通信方式中:設(shè)備節(jié)點(diǎn)適合于驅(qū)動程序開發(fā),但只支持單工傳輸;Proc與sysfs文件使用方便,但不支持傳輸大數(shù)據(jù);內(nèi)存映射傳輸效率最高,但誤操作時會對系統(tǒng)造成嚴(yán)重破壞;Netlink則使用很靈活,能滿足大多數(shù)用戶需求。
本文首先介紹Netlink套接字基本使用方法與通信流程,然后詳細(xì)闡述使用Netlink如何實(shí)現(xiàn)多線程并發(fā)與消息異步處理通信,最后在真實(shí)硬件平臺上對該機(jī)制進(jìn)行驗(yàn)證。
1Netlink機(jī)制概述
Netlink機(jī)制包含用戶態(tài)接口與內(nèi)核態(tài)接口,其中用戶態(tài)沿用標(biāo)準(zhǔn)的socket接口,內(nèi)核態(tài)則提供了專用接口。
1.1用戶態(tài)Netlink接口
Netlink用戶態(tài)接口與BSD套接字接口基本一致,包括:socket()、bind()、sendmsg()、recvmsg()、close等常用接口。
1.1.1Netlink套接字創(chuàng)建
int socket(int domain, int type, int protocol)
其中,domain參數(shù)為AF_NETLINK或PF_NETLINK,表示使用Netlink協(xié)議,type參數(shù)是SOCK_RAW或SOCK_DGRAM,代表Netlink面向數(shù)據(jù)報(bào),最后一個參數(shù)指定Netlink協(xié)議類型,除了內(nèi)核中已經(jīng)定義的類型,用戶還可以定義自己的協(xié)議類型。
1.1.2套接字地址綁定
int bind(fd, (struct sockaddr*)&nladdr, sizeof(struct sockaddr_nl))
函數(shù)bind()用于Netlink套接字句柄與Netlink源地址綁定。第一個參數(shù)為創(chuàng)建Netlink套接字時獲取的描述符,第二個為Netlink源地址結(jié)構(gòu)指針,最后一個參數(shù)為Netlink源地址結(jié)構(gòu)大小。
Netlink socket地址定義如下:
struct sockaddr_nl {
_kernel_sa_family_t nl_family;/*AF_NETLINK*/endprint
unsigned short nl_pad; /* zero */
_u32 nl_pid; /* port ID */
_u32 nl_groups; /* multicast groups mask */
};
其中:nl_family代表協(xié)議類型,設(shè)置為AF_NETLINK或者PF_NETLINK;字段nl_pad保留,默認(rèn)設(shè)置為0;nl_pid代表Netlink socket的本地地址,為確保消息發(fā)送準(zhǔn)確性,其設(shè)置非常關(guān)鍵,必須確保唯一性;字段nl_groups用于設(shè)置多播組,如果設(shè)置為0,表示進(jìn)行單播。
1.1.3Netlink消息發(fā)送
int sendmsg(int sock, struct msghdr *msg, int flags)
Netlink發(fā)送消息前需要填充信息,信息由消息頭與數(shù)據(jù)部分組成,其結(jié)構(gòu)如圖2所示。
圖2Netlink消息頭
消息長度代表Netlink消息的總長度,包括消息頭長度與數(shù)據(jù)部分長度;應(yīng)用內(nèi)部定義消息類型,大部分情況下設(shè)置為0;標(biāo)志用于設(shè)置消息標(biāo)志,內(nèi)核讀取與修改這類標(biāo)志,通常不需修改,默認(rèn)為0,在一些高級應(yīng)用(如路由daemon)中需要設(shè)置它進(jìn)行特殊操作;字段序列號與消息端口號用于應(yīng)用追蹤消息來源,分別表示消息發(fā)送順序號與來源端口號。
1.1.4Netlink消息接收
int recvmsg(int sock, struct msghdr *msg, int flags)
應(yīng)用接收消息時,首先需要為消息頭與數(shù)據(jù)部分分配足夠空間,然后填充消息頭。
1.1.5關(guān)閉Netlink套接字
Close函數(shù)用于關(guān)閉套接字,釋放資源。
1.2內(nèi)核態(tài)Netlink接口
Linux內(nèi)核包含一套專門的接口函數(shù),接收用戶程序發(fā)送的數(shù)據(jù)以及將處理完數(shù)據(jù)發(fā)送回用戶程序。
1.2.1內(nèi)核態(tài)Netlink套接字創(chuàng)建
struct sock*netlink_kernel_create(struct net*net, int unit, struct netlink_kernel_cfg*cfg)
netlink_kernel_create函數(shù)在不同內(nèi)核版本間變化非常大,在使用過程中,需要查找與內(nèi)核匹配的函數(shù)定義。在3.0以上版本中,該函數(shù)包含3個參數(shù):第一個參數(shù)指定網(wǎng)絡(luò)名字空間,默認(rèn)為init_net全局變量;第二個參數(shù)設(shè)置Netlink協(xié)議類型,需要與用戶態(tài)定義一致;第三個參數(shù)用于指定內(nèi)核態(tài)Netlink配置信息。其結(jié)構(gòu)為:
struct netlink_kernel_cfg {
unsigned int groups;
unsigned int flags;
void (*input)(struct sk_buff *skb);
struct mutex *cb_mutex;
int (*bind)(struct net *net, int group);
void (*unbind)(struct net *net, int group);
bool (*compare)(struct net *net, struct sock *sk); }
通常用戶只需設(shè)置groups與input字段:Groups用于設(shè)置單播還是組播;input用于注冊消息回調(diào)處理函數(shù),當(dāng)內(nèi)核接收到用戶發(fā)來的Netlink信息后會自動調(diào)用它。
1.2.2從內(nèi)核態(tài)向用戶態(tài)發(fā)送數(shù)據(jù)
Netlink支持單播與組播,因此內(nèi)核態(tài)信息發(fā)送函數(shù)包括兩個。
單播:
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock)
第一個參數(shù)為內(nèi)核Netlink套接字句柄;第二個參數(shù)存放消息結(jié)構(gòu),數(shù)據(jù)字段為發(fā)送的Netlink消息;控制塊則包含消息地址信息;第三個參數(shù)portid為接收對象的Netlink地址,最后一個用于設(shè)置阻塞屬性。
組播:
int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 portid,__u32 group, gfp_t allocation)
前3個參數(shù)與單播一樣,第四個參數(shù)用于指定接收消息的多播組,最后一個參數(shù)則為內(nèi)核內(nèi)存分配類型。
1.3Netlink內(nèi)核態(tài)與用戶態(tài)通信流程
用戶程序通過Netlink機(jī)制與內(nèi)核進(jìn)行通信,流程如圖3所示。
圖3Netlink用戶態(tài)與內(nèi)核態(tài)交互流程
用戶態(tài)Netlink使用流程與常用BSD Socket一樣,首先使用socket函數(shù)創(chuàng)建套接字,然后使用bind函數(shù)綁定地址,封裝并使用sendmsg向內(nèi)核發(fā)送消息,接著使用recvmsg接收消息,最后通過close函數(shù)關(guān)閉套接字,釋放資源。內(nèi)核態(tài)處理過程類似,發(fā)送消息時還可以根據(jù)需要選擇單播或者多播。
2機(jī)制設(shè)計(jì)
Netlink作為socket的一個變種,本身就支持并發(fā)與異步處理,但是需要針對線程中Netlink socket本地地址設(shè)置與消息接收處理松耦合進(jìn)行特殊設(shè)計(jì)。
2.1線程N(yùn)etlink本地地址生成方法
Netlink并發(fā)實(shí)現(xiàn)的關(guān)鍵點(diǎn)是套接字創(chuàng)建時地址設(shè)置的唯一性。Bind函數(shù)負(fù)責(zé)給Netlink套接字命名,將本地地址與其相關(guān)聯(lián)。上文已經(jīng)介紹了結(jié)構(gòu)體sockaddr_nl中nl_pid字段用于代表32位本地地址,其在填充時必須保證唯一性才能確保收發(fā)消息的準(zhǔn)確性。endprint
如果用戶程序?qū)崿F(xiàn)的是進(jìn)程級并發(fā),可以采用進(jìn)程號作為nl_pid的值,進(jìn)程號在系統(tǒng)中的唯一性確保了Netlink本地地址的唯一性。
但是如果進(jìn)程中多個線程需要創(chuàng)建各自獨(dú)立的Netlink socket,基于線程共享進(jìn)程號的原因,進(jìn)程號就不能用于區(qū)分線程創(chuàng)建的Netlink套接字地址。目前流傳最廣泛的線程N(yùn)etlink中nl_pid創(chuàng)建方法為[12]:
pthread_self() 16 | getpid()
其中,nl_pid由線程自身ID后半部與其所屬進(jìn)程pid拼接而成,期望由pid在系統(tǒng)的唯一性與pthread_self在進(jìn)程中的唯一性,保證nl_pid在全系統(tǒng)的唯一性。但在實(shí)際使用中,生成的值并不唯一。圖4是在ubuntu 14.04中創(chuàng)建10個線程生成的pid、tid(pthread_self返回值)與nl_pid結(jié)果。如圖4所示,10個樣本中就出現(xiàn)了重復(fù)。
圖4線程地址示例圖
從圖4中可以發(fā)現(xiàn),pthread_self低16位有12位重復(fù),pthread_self()16后只有高4位發(fā)生變化,由于pid一般小于65 536,因此進(jìn)程中創(chuàng)建n個線程,使用pthread_self()16 | getpid()出現(xiàn)重復(fù)數(shù)據(jù)的概率為:
1-15!(16-n)!×16n-1(1 運(yùn)行10次出現(xiàn)重復(fù)的概率約為85%,而創(chuàng)建17個以上線程nl_pid重復(fù)概率就已經(jīng)為1。 分析pthread_self實(shí)現(xiàn),可以發(fā)現(xiàn)其實(shí)際獲取的是線程TCB地址相對于進(jìn)程數(shù)據(jù)段的偏移,所以低地址一致,造成按上述方法生成nl_pid出現(xiàn)重復(fù)。 因此,為了保證線程中Netlink套接字正常使用,需要重新設(shè)計(jì)nl_pid生成公式??疾靝thread_self的實(shí)現(xiàn),它在進(jìn)程內(nèi)唯一而且后半部基本一致,因此可以考慮取其前半部與線程pid進(jìn)行拼接,從而確保生成nl_pid在全系統(tǒng)的唯一性。新生成方法如下: pthread_self()16 | getpid()16 一個支持多線程并發(fā)的Netlink用戶態(tài)示例用例如下,所有nl_pid設(shè)置都使用新方法: struct sockaddr_nl src_addr, dest_addr; struct nlmsghdr* nlh = NULL; struct iovec iov; struct msghdr msg; /**建立用戶空間netlink套接字*/ sock_nl=socket(AF_NETLINK, SOCK_RAW, LinuxV_NL_P_TYPE); /**填充SRC_ADDR并進(jìn)行端口綁定*/ memset(&src_addr, 0, sizeof(struct sockaddr_nl)); src_addr.nl_family=AF_NETLINK; /**按照新公式定義本地地址*/ src_addr.nl_pid=pthread_self()16 | getpid()16; src_addr.nl_groups = 0; /**綁定netlink套接字,在nl_pid端口監(jiān)聽*/ bind(sock_nl, (struct sockaddr*)&src_addr, sizeof(struct sockaddr_nl); /**封裝Netlink消息*/ dest_addr.nl_family=AF_NETLINK; dest_addr.nl_pid=0; /**to Linux kernel*/ dest_addr.nl_groups=0; /**填充netlink命令包頭*/ nlh=(struct nlmsghdr*)malloc(NLMSG_LENGTH(MAX_PAYLOAD)); nlh->nlmsg_type=MY_TYPE_0; /**注意保持和初始化時nl_pid一致,用于確定消息來源*/ nlh->nlmsg_pid=pthread_self()16 | getpid()16; /**填充發(fā)送命令報(bào)內(nèi)容*/ memcpy(NLMSG_DATA(nlh), buf, buflen); /**構(gòu)造Netlink消息包*/ iov.iov_base=(void*)nlh; msg.msg_name=(void*)&dest_addr; msg.msg_iov=&iov; /**發(fā)送netlink包*/ sendmsg(sock_nl, &msg, 0); /**接收netlink包*/ recvmsg(sock_nl, &msg, 0); close(sock_nl) 2.2內(nèi)核Netlink消息異步處理機(jī)制 Netlink是BSD套接字的一種,繼承了其異步處理特性,用戶程序發(fā)送消息并把消息保存到接收者的接收隊(duì)列后,不需要一直等待內(nèi)核處理完消息。 為了提高異步處理效率,在內(nèi)核態(tài)可以將Netlink信息的接收與處理過程松耦合,這樣內(nèi)核收到用戶發(fā)來的消息后只負(fù)責(zé)喚醒處理內(nèi)核線程,然后就返回。所有的消息處理工作由處理線程完成,從而可以實(shí)現(xiàn)用戶程序持續(xù)快速發(fā)送Netlink消息到內(nèi)核,提高吞吐率。特別是如果應(yīng)用程序發(fā)送信息處理流程不同,就可以創(chuàng)建多個內(nèi)核線程進(jìn)行并發(fā)處理。在內(nèi)核3.12.11上內(nèi)核態(tài)Netlink創(chuàng)建與消息異步收發(fā)實(shí)現(xiàn)代碼如下:
struct netlink_kernel_cfg cfg={
.groups=0,
.input=receive_us_msg,
};
nl_sk=netlink_kernel_create(&init_net,LinuxV_NL_P_TYPE, &cfg);
/**創(chuàng)建netlink消息處理內(nèi)核線程*/
nl_msg_thread=kthread_run(nlmsg_process_thread, NULL, "process");
void receive_us_msg(struct sk_buff* skb)
{
struct sk_buff* nl_skb=NULL;
nl_skb=skb_copy(skb,GFP_ATOMIC);
if(nl_skb)
skb_queue_tail(&(nl_sk->sk_receive_queue),nl_skb);
wake_up_interruptible(sk_sleep(nl_sk));
}
/*nlmsg_process_thread函數(shù)負(fù)責(zé)處理Netlink消息并回傳用戶程序*/
3實(shí)驗(yàn)平臺與測試方法
為了驗(yàn)證本文Netlink多線程并發(fā)機(jī)制的穩(wěn)定性與擴(kuò)展性,測試將在32位與64位Linux系統(tǒng)上進(jìn)行。測試機(jī)具體配置如表1、表2所示。
在測試中,檢驗(yàn)使用上述方法進(jìn)程能創(chuàng)建包含Netlink連接的線程數(shù)量。如果進(jìn)程中不同線程生成的nl_pid一致,Netlink將創(chuàng)建失敗。在32位系統(tǒng)上,進(jìn)程可以使用的虛擬用戶地址空間為3GB,其創(chuàng)建線程分配的線程空間大小總和不能超過這個限制,因此系統(tǒng)中進(jìn)程能創(chuàng)建的線程數(shù)量取決于線程堆棧大小,在實(shí)驗(yàn)中通過ulimit命令設(shè)置不同的線程堆棧大小,然后記錄進(jìn)程能創(chuàng)建的最大線程數(shù)量,看其是否與理論值相符。在64位機(jī)器上,由于虛擬地址空間可以達(dá)到TB級,因此測試時首先設(shè)置系統(tǒng)最大可創(chuàng)建線程數(shù),然后通過測試程序記錄實(shí)際能創(chuàng)建的最大線程數(shù)量,看其是否與設(shè)置值相符。
4實(shí)驗(yàn)結(jié)果與分析
在32位操作系統(tǒng)上測試結(jié)果如表3所示。
試驗(yàn)顯示,在32位操作系統(tǒng)上,線程堆棧為2M時,創(chuàng)建線程數(shù)量為1 449,這個值與理論最大值相符,因?yàn)樵?2位Linux操作系統(tǒng)下進(jìn)程用戶空間大小為3G(3 072M),用3 072M除以2M得1 536,但實(shí)際測試用例中代碼段與數(shù)據(jù)段等占用大概1KB,這個值應(yīng)該為1 400多。同理,內(nèi)核堆棧為4M、8M、16M時,線程數(shù)量與理論最大值相符合。
在64位操作系統(tǒng)上測試結(jié)果如表4所示。
系統(tǒng)中最大線程數(shù)量值設(shè)置為32 768,測試結(jié)果顯示,不同大小線程堆棧情況下創(chuàng)建的線程數(shù)量與系統(tǒng)線程最大值相差不大,符合預(yù)期,完全能夠滿足實(shí)際應(yīng)用需求。
5結(jié)語
Netlink socket是Linux系統(tǒng)中用戶程序與內(nèi)核模塊之間一種很靈活的通信方式,它使用方便,提供了全雙工、緩沖I/O、多點(diǎn)傳送及異步通訊等高級特性,應(yīng)用極其廣泛。但是,Netlink在內(nèi)核不同版本中變化非常大,目前公開資料上提供的線程并發(fā)與消息接收處理松耦合方法存在錯誤,也不適應(yīng)當(dāng)前內(nèi)核版本。本文分析了Netlink socket本地地址nl_pid流行計(jì)算公式的錯誤原因,設(shè)計(jì)了新的計(jì)算公式,并在真實(shí)機(jī)器上進(jìn)行了驗(yàn)證,測試結(jié)果顯示新計(jì)算公式能真正支持線程中Netlink的使用。同時,還針對當(dāng)前內(nèi)核版本,設(shè)計(jì)了切實(shí)可用的消息接收與處理松耦合流程,實(shí)現(xiàn)了上層應(yīng)用程序的快速響應(yīng)。
但是,由于Netlink是基于BSD socket實(shí)現(xiàn)的,其通信過程耗時非常大,傳輸效率不高,在今后工作中可以考慮結(jié)合其它傳輸機(jī)制,實(shí)現(xiàn)快捷高效的內(nèi)核態(tài)與用戶態(tài)數(shù)據(jù)通信。
參考文獻(xiàn)參考文獻(xiàn):
[1]ROBERT L. Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)[M].陳莉君,康華,張波,譯.北京:機(jī)械工業(yè)出版社,2006.
[2]NEIRA-AYUSO P, GASCA R M, LEFEVRE L. Communicating between the kernel and userspace in Linux using Netlink sockets[J]. Software Practice & Experience,2013,40(9):797–810.
[3]CORBET J, RUBINI A, KROAHHARTMAN G. Linux device drivers[M]. Cambridge :O'Reilly Media, Inc.2005.
[4]郭松,謝維波.Linux視域下Proc文件系統(tǒng)的編程剖析[J].華僑大學(xué)學(xué)報(bào):自然科學(xué)版,2010,31(5):515520.
[5]MOCHEL P. The sysfs filesystem[J]. Proceedings of Annual Linux Symposium,2005(1):313326.
[6]STEVENS W R,RAGO S A. UNIX環(huán)境高級編程[M].尤晉元,譯.北京:人民郵電出版社,2009.
[7]SALIM J, KHOSRAVI H, KLEEN A, et al. Linux Netlink as an IP services protocol[J]. International Journal of Developmental Neuroscience,2003,28(8):94.
[8]KENT S, SEO K. RFC4301: security architecture for internet protocol (IPSec)[M]. Los Angeles: RFC Editor,2005.
[9]PURDY G N. Linux iptablespocket reference: firewalls, nat and accounting[M]. Sebastopol, CA: OReilly Media, Inc,2004.
[10]ROSEN. Netfilter[M]. Berkeley, CA: Linux Kernel Networking Apress,2014.
[11]劉斌,朱程榮.Linux內(nèi)核與用戶空間通信機(jī)制研究[J].電腦知識與技術(shù),2012,8(16):38163817.
[12]HE K K. Why and how to use Netlink socket[J]. Linux Journal,2005,11(130):1419.
責(zé)任編輯(責(zé)任編輯:何麗)endprint