最近用了一下netlink,比較方便。特將netlink編程中的注意事項列下:
1、選一個沒有用到的協議類型,注意要避開netlink.h中已經定義好的類型。注意保證核心層和使用者層的協議類類型的一致。也就是說核心層建立netlink函數netlink_kernel_create的第一個參數和使用者層建立socket的socket函數的第三個參數要一致。否則是不能建立串連的。
2、版本問題。如果你在網上搜到一個文章說netlink代碼保證可用,你滿心歡喜把代碼貼到自己機器上,八成是不能用。因為netlink在linux2.6.XX的版本中變化的太快了。在核心態,大致有這麼幾個地方會隨著版本的變化而變化: a)netlink_kernel_create函數的原型;b)nlmsg_put/NLMSG_PUT的原型。
貼一下My Code,估計也不是很全面:
a) netlink_kernel_create函數的原型:
//init_net是一個核心變數
#if LINUX_VERSION_CODE >= 0x020618
fspwfd = netlink_kernel_create(&init_net,NETLINK_TYPE, 0, yourHandler, NULL,THIS_MODULE);
#elif LINUX_VERSION_CODE >= 0x020616
fspwfd = netlink_kernel_create(NETLINK_TYPE, 0, yourHandler, NULL,THIS_MODULE);
#elif LINUX_VERSION_CODE >= 0x020610
fspwfd = netlink_kernel_create(NETLINK_TYPE, 0, yourHandler,THIS_MODULE);
#else
fspwfd = netlink_kernel_create(NETLINK_TYPE, yourHandler);
#endif
b)核心像應用程式層單播時:
#if LINUX_VERSION_CODE >=0x020616
nlhdr = nlmsg_put(skb,0,0,0,(NLMSG_SPACE(1024)-sizeof(struct nlmsghdr)),0);
#else
nlhdr = NLMSG_PUT(skb,0,0,0,(NLMSG_SPACE(1024)-sizeof(struct nlmsghdr)));
#endif
//當核心版本小於0x020616時,還需要做一個出錯時的跳轉標籤
#if LINUX_VERSION_CODE < 0x020616
nlmsg_failure:
#endif
C)yourHandler的原型:
#if LINUX_VERSION_CODE >= 0x02061B:
Handle原型為:
void handler(struct sk_buff *__skb)
通過skb = skb_get(__skb);得到實際資料
#else:
yourHandler原型為:
void handler (struct sock *sk, int len)
通過skb = skb_dequeue(&sk->sk_receive_queue)得到實際資料。
#endif
3、NLMSG_DATA(nlhdr)記憶體空間是交給socket來處理的。
4、一個進程中多個線程使用netlink。此時用進程id無法唯一的確定一個netlink通訊。需要把表示號設為pthread_self() << 16 | getpid();
祝你好運~~~