亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 23859 | 回復: 0
打印 上一主題 下一主題

[通信方式] 使用netlink通訊時需要注意的一些問題 [復制鏈接]

論壇徽章:
169
申猴
日期:2013-10-09 10:10:16天秤座
日期:2013-10-10 15:28:08天蝎座
日期:2014-07-17 14:02:54丑牛
日期:2014-07-17 14:03:04處女座
日期:2014-07-17 14:03:12雙子座
日期:2014-07-17 14:03:21天秤座
日期:2014-07-17 14:03:29酉雞
日期:2014-07-17 14:03:39金牛座
日期:2014-07-21 10:37:54水瓶座
日期:2014-07-22 16:56:09巳蛇
日期:2014-07-23 11:48:03天蝎座
日期:2014-07-31 10:16:36
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2019-07-26 14:02 |只看該作者 |倒序瀏覽
使用netlink通訊時需要注意的一些問題   原作者:duanjigang


之前發(fā)過一個用戶態(tài)通過netlink從內(nèi)核中獲取網(wǎng)絡(luò)卡列表以及每個網(wǎng)卡狀態(tài)信息的例子

大概的原理就是內(nèi)核創(chuàng)建netlink socket,然后用戶態(tài)調(diào)用應用程序發(fā)送查詢命令,或者獲取所有網(wǎng)卡列表,或者獲取某一個網(wǎng)卡的狀態(tài)信息。
當時做的比較簡單,也就過去了,最近要用到這個通訊,傳輸比較大量數(shù)據(jù),遇到了一些問題,今天剛剛解決,稍微小結(jié)下,發(fā)上來。
希望能對大家有點用(估計很多高手早都注意這個問題了^_^)

首先列舉下問題:
其一,內(nèi)核多次發(fā)送數(shù)據(jù)的問題。
在上篇文章中,我們看到,kernel是收到一個命令,就獲取數(shù)據(jù),然后簡單的完成一次發(fā)送,代碼片段如下:
  •         nlhdr->nlmsg_pid = 0;
  •                    nlhdr->nlmsg_flags = 0;
  •                    NETLINK_CB(skb).pid = 0;
  •                     NETLINK_CB(skb).dst_pid = pid;
  •                     NETLINK_CB(skb).dst_group = 0;
  •                     memset(nlhdr, 0, NLMSG_SPACE(nlhdr->nlmsg_len));
  •                     strcpy(NLMSG_DATA(nlhdr), szBuff);
  •                     netlink_unicast(netlink_exam_sock, skb, pid, MSG_DONTWAIT);
復制代碼

當時沒太注意,后來遇到情況是,數(shù)據(jù)有多條,內(nèi)核需要多次發(fā)送,怎么辦??結(jié)果我嘗試用netlink_unicast多次發(fā)送,比如
  • for (int i = 0; i < n ;i++)
  • {
  •    //make data for record i
  •    netlink_unicast(netlink_exam_sock, skb, pid, MSG_DONTWAIT);
  • }

復制代碼

結(jié)果一運行,就崩潰,后來知道netlink_unicast發(fā)送后會把skb釋放掉,所以第二次調(diào)用是無效的了,這才會崩潰。
大體上感覺在每次發(fā)送的時候,可能需要clone一個或者自己構(gòu)造一個包發(fā)送,上文的例子中的是直接利用從隊列中拿出來的
skb做為負載發(fā)送的,所以沒問題,但是還不能偷懶。就在網(wǎng)上找資料。
終于還是找到說法了,居然也是在CU的帖子,就是另外寫一個函數(shù),自己構(gòu)造包,填數(shù)據(jù),然后發(fā)送,就能多次發(fā)送了。
參考“執(zhí)一”的博文:
通過Netlink與TC進行通信
(讓我們再次對九賤兄和執(zhí)一表示感謝!)修改了下,寫(基本上是copy,只不過修改了參數(shù))了個發(fā)送的函數(shù),如下:
  • static int send_to_user(struct sock * ps, int pid, const char* szdata, unsigned int len)
  • {
  •         int ret;
  •         int size;
  •         unsigned char *old_tail;
  •         struct sk_buff *skb;
  •         struct nlmsghdr *nlhdr;
  •         struct cha *packet;
  •         /*計算消息總長:消息首部加上數(shù)據(jù)加度*/
  •         size = NLMSG_SPACE(len);
  •         /*分配一個新的套接字緩存*/
  •         skb = alloc_skb(size, GFP_ATOMIC);
  •         old_tail = skb->tail;
  •         /*初始化一個netlink消息首部*/
  •         nlhdr = NLMSG_PUT(skb, 0, 0, NETLINK_CME, size - sizeof(*nlhdr));
  •         /*跳過消息首部,指向數(shù)據(jù)區(qū)*/
  •         packet = NLMSG_DATA(nlhdr);
  •         /*初始化數(shù)據(jù)區(qū)*/
  •         memset(packet, 0, len);
  •         memcpy(packet, szdata, len);
  •         nlhdr->nlmsg_len = skb->tail - old_tail;
  •         /*設(shè)置控制字段*/
  •         nlhdr->nlmsg_pid = 0;
  •         nlhdr->nlmsg_flags = 0;
  •         NETLINK_CB(skb).pid = 0;
  •         NETLINK_CB(skb).dst_pid = pid;
  •         NETLINK_CB(skb).dst_group = 0;
  •         /*發(fā)送數(shù)據(jù)*/
  •         ret = netlink_unicast(ps, skb, pid, MSG_DONTWAIT);
  •         nlmsg_failure:
  •         return ret;
  •         ;
  • }

復制代碼

這樣,把原來的代碼稍作修改
改成這樣就能多次發(fā)送了。
  • if(strncmp(data, "all", 3) == 0)
  •                     {
  •                         get_dev_info(0, NULL);
  •                     }
  •                     else
  •                     {
  •                         get_dev_info(1, data);
  •                     }
  •                     pid = nlhdr->nlmsg_pid;
  •                     for(i = 0; i < time; i++)
  •                 {
  •                         send_to_user(netlink_exam_sock, pid, szBuff, strlen(szBuff));
  •                 }
  •         }

復制代碼


其二:skb釋放問題。(問題解決按照輕重緩急來說^_^)

剛解決了多次發(fā)送的問題,我就有些得意忘形,結(jié)果dmesg時看到一個很2的信息,是在rmmod時報告的

KERNEL: assertion (!atomic_read(&sk->sk_rmem_alloc)) failed at net/netlink/af_netlink.c (145)

于是再想是不是一樓了什么東西,哦,從隊列中拿出來的skb沒有釋放,這下好解決了。兩種途徑。
A:既然netlink_unicast發(fā)送完后會把skb釋放掉,那我們?yōu)樯恫坏谝淮伟l(fā)送時用從隊列中拿出來的skb做載體,這樣既發(fā)送數(shù)據(jù)包,又
釋放了skb,果然,報錯沒了。。真是得了便宜還賣乖啊
B:最簡單的,直接釋放掉從隊列拿出來的skb,從一而終的構(gòu)造包發(fā)送,不再腳踩兩只船。
  • kfree_skb(skb);

復制代碼

好了,第二個問題解決了。

其三:也是最末的。應用層的阻塞讀問題。
以前我都是一次sendto,然后內(nèi)核一個回復,應用層再一個recvfrm就了事了。
結(jié)果后來改成
  • while(1)
  • {
  •     recvfrom();
  •     //把數(shù)據(jù)入庫
  • }

復制代碼

的方式,發(fā)現(xiàn)后面的語句沒執(zhí)行,發(fā)現(xiàn)是recvfrom阻塞住了。。這個好辦,要讓while循環(huán)跳出,內(nèi)核通知應用層:“我沒數(shù)據(jù)了,別再再苦苦追尋了,不要浪費你時間”。。這似乎聽起來有些悲哀啊,呵呵
這種人來的語言用程序來寫就是IP報文的分片標志吧,那就自己做個標志吧。
可以這樣做,自己定一個消息頭,放在netlink消息的開始位置,大小固定,或者直接放一個整數(shù)都行,反正就是用來標識是否還有數(shù)據(jù)的。
當內(nèi)核中還有數(shù)據(jù)要發(fā)送時,每次發(fā)送消息中,這個標志位為1,告訴他:“你還有希望,繼續(xù)追”
如果沒有數(shù)據(jù)了,發(fā)送一個空包或者帶數(shù)據(jù)的報文,其中標志位為0,告訴他:“我已經(jīng)領(lǐng)證了,終止吧”,用戶態(tài)讀到這個
標志位,跳出循環(huán),后續(xù)工作繼續(xù)。。

就以上這三個問題,是我實際中遇到的,希望對大家有用。





您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP