2009年2月11日 星期三

Netlink (1) 基礎

Netlink 是一種在內核與用戶應用間進行雙向數據傳輸的非常好的模式,用戶使用標準的 socket API 就可以使用 netlink 提供的強大功能,內核需要使用專門的內核 API 來使用 netlink。我們可以從man中看到它的簡介。

NAME
netlink, PF_NETLINK - Communication between kernel and user

SYNOPSIS
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>

netlink_socket = socket(PF_NETLINK, socket_type, netlink_family);


Netlink 相對於系統調用,ioctl 以及 /proc 檔案系統而言具有以下優點︰
1. 為了使用 netlink,用戶僅需要在 include/linux/netlink.h 中增加一個新類型的 netlink 協議定義即可, 如 #define NETLINK_MYTEST 17 然後,內核和用戶態應用就可以立即透過 socket API 使用該 netlink 協議類型進行數據交換。但系統調用需要增加新的系統調用,ioctl 則需要增加設備或檔案, 那需要不少代碼,proc 檔案系統則需要在 /proc 下添加新的檔案或目錄,那將使本來就混亂的 /proc 更加混亂。

2. netlink是一種異步通信機制,在內核與用戶態應用之間傳遞的消息儲存在socket緩沖隊列中,發送消息只是把消息儲存在接收者的socket的接收隊列,而不需要等待接收者收到消息,但系統調用與 ioctl 則是同步通信機制,如果傳遞的數據太長,將影響調度。

3. 使用 netlink 的內核部分可以採用模塊的模式實現,使用 netlink 的應用部分和內核部分沒有編譯時倚賴,但系統調用就有倚賴,而且新的系統調用的實現必須靜態地連接到內核中,它無法在模塊中實現,使用新系統調用的應用在編譯時需要倚賴內核。

4. netlink 支援多播,內核模塊或應用可以把消息多播給一個netlink組,屬於該neilink 組的任何內核模塊或應用都能接收到該消息,內核事件向用戶態的通知機製就使用了這一特性,任何對內核事件感興趣的應用都能收到該子系統發送的內核事件,在後面的文章中將介紹這一機製的使用。

5. 內核可以使用 netlink 首先發起會話,但系統調用和 ioctl 只能由用戶應用發起調用。

6. netlink 使用標準的 socket API,因此很容易使用,但系統調用和 ioctl 則需要專門的培養訓練才能使用。


接下來看一下socket的參數
netlink_socket = socket(PF_NETLINK, socket_type, netlink_family);

socket_type: SOCK_RAW or SOCK_DGRAM,Both can do.
netlink_family: define in kernel source include/linux/netlink.h

#define NETLINK_ROUTE 0 /* Routing/device hook */
#define NETLINK_W1 1 /* 1-wire subsystem */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
#define NETLINK_FIREWALL 3 /* Firewalling */
#define NETLINK_INET_DIAG 4 /* INET socket monitoring */
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
#define NETLINK_XFRM 6 /* ipsec */
#define NETLINK_SELINUX 7 /* SELinux event notifications */
#define NETLINK_ISCSI 8 /* Open-iSCSI */
#define NETLINK_AUDIT 9 /* auditing */
#define NETLINK_FIB_LOOKUP 10
#define NETLINK_CONNECTOR 11
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC 16

retval = bind(netlink_socket, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
函數 bind() 用於把一個打開的 netlink socket 與 netlink socket 位址綁定在一起。netlink socket 的位址架構如下︰

struct sockaddr_nl
{
sa_family_t nl_family;
unsigned short nl_pad;
__u32 nl_pid;
__u32 nl_groups;
};


參考資料:
http://eddiefu.bokee.com/viewdiary.14137760.html

http://blog.csdn.net/absurd/archive/2008/11/07/3244482.aspx

沒有留言: