真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

linux中用戶程序同內(nèi)核通信的示例分析

這篇文章主要介紹了linux中用戶程序同內(nèi)核通信的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

為謝通門等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及謝通門網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、謝通門網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

簡(jiǎn)介

linux下用戶程序同內(nèi)核通信的方式一般有ioctl, proc文件系統(tǒng),剩下一個(gè)就是Netlink套接字了。 這里先介紹下netlink。

Netlink 是一種在內(nèi)核與用戶應(yīng)用間進(jìn)行雙向數(shù)據(jù)傳輸?shù)姆浅:玫姆绞?,用戶態(tài)應(yīng)用使用標(biāo)準(zhǔn)的 socket API 就可以使用 netlink 提供的強(qiáng)大功能,內(nèi)核態(tài)需要使用專門的內(nèi)核 API 來使用 netlink。

Netlink 相對(duì)于系統(tǒng)調(diào)用,ioctl 以及 /proc 文件系統(tǒng)而言具有以下優(yōu)點(diǎn):

1,為了使用 netlink,用戶僅需要在 include/linux/netlink.h 中增加一個(gè)新類型的 netlink 協(xié)議定義即可, 如 #define NETLINK_MYTEST 17 然后,內(nèi)核和用戶態(tài)應(yīng)用就可以立即通過 socket API 使用該 netlink 協(xié)議類型進(jìn)行數(shù)據(jù)交換。但系統(tǒng)調(diào)用需要增加新的系統(tǒng)調(diào)用,ioctl 則需要增加設(shè)備或文件, 那需要不少代碼,proc 文件系統(tǒng)則需要在 /proc 下添加新的文件或目錄,那將使本來就混亂的 /proc 更加混亂。

2. netlink是一種異步通信機(jī)制,在內(nèi)核與用戶態(tài)應(yīng)用之間傳遞的消息保存在socket緩存隊(duì)列中,發(fā)送消息只是把消息保存在接收者的socket的接 收隊(duì)列,而不需要等待接收者收到消息,但系統(tǒng)調(diào)用與 ioctl 則是同步通信機(jī)制,如果傳遞的數(shù)據(jù)太長(zhǎng),將影響調(diào)度粒度。

3.使用 netlink 的內(nèi)核部分可以采用模塊的方式實(shí)現(xiàn),使用 netlink 的應(yīng)用部分和內(nèi)核部分沒有編譯時(shí)依賴,但系統(tǒng)調(diào)用就有依賴,而且新的系統(tǒng)調(diào)用的實(shí)現(xiàn)必須靜態(tài)地連接到內(nèi)核中,它無法在模塊中實(shí)現(xiàn),使用新系統(tǒng)調(diào)用的應(yīng)用在編譯時(shí)需要依賴內(nèi)核。

4.netlink 支持多播,內(nèi)核模塊或應(yīng)用可以把消息多播給一個(gè)netlink組,屬于該neilink 組的任何內(nèi)核模塊或應(yīng)用都能接收到該消息,內(nèi)核事件向用戶態(tài)的通知機(jī)制就使用了這一特性,任何對(duì)內(nèi)核事件感興趣的應(yīng)用都能收到該子系統(tǒng)發(fā)送的內(nèi)核事件,在 后面的文章中將介紹這一機(jī)制的使用。

5.內(nèi)核可以使用 netlink 首先發(fā)起會(huì)話,但系統(tǒng)調(diào)用和 ioctl 只能由用戶應(yīng)用發(fā)起調(diào)用。

6.netlink 使用標(biāo)準(zhǔn)的 socket API,因此很容易使用,但系統(tǒng)調(diào)用和 ioctl則需要專門的培訓(xùn)才能使用。

下面這兩部分代碼主要的目的是用netlink機(jī)制實(shí)現(xiàn)用戶程序和內(nèi)核的通信。 具體就是用戶程序執(zhí)行./netlink -S [我是參數(shù)] 或./netlink -G 時(shí),內(nèi)核會(huì)返回"S know you!" 和“I know you!” 這兩種字符串, 然后輸出。 內(nèi)核和用戶程序均加有打印。

內(nèi)核模塊

1. Makefile依賴的編譯規(guī)則 ruler.dir

PWD := $(shell pwd) 
 
all: modules romfs 
 
modules: 
 $(MAKE) -C $(KDIR) M=$(PWD) modules 
 @echo $(OBJ) 
 
modules_install: 
 $(MAKE) -C $(KDIR) M=$(PWD) modules_install 
 
romfs: 
 cp -rf *.ko $(MODULES_BUILD_DIR) 
 
clean: 
 rm *.o *.ko *.mod.* Module.* modules.* 
 rm -rf $(MODULES_BUILD_DIR) 
 
obj-m := $(MOD_NAME).o

2.Makefile

KERNEL_MODULES := netlink 
 
export MODULES_ROOT_DIR := $(shell pwd) 
export MODULES_BUILD_DIR := $(MODULES_ROOT_DIR)/build 
export KDIR := /lib/modules/$(shell uname -r)/build #這行是為了取出系統(tǒng)下內(nèi)核的目錄(ubuntu) 
 
all: init modules romfs 
 
init: 
 mkdir -p $(MODULES_BUILD_DIR) 
 
modules:$(patsubst %, _dir_%, $(KERNEL_MODULES)) 
 
$(patsubst %, _dir_%, $(KERNEL_MODULES)): 
 @echo 
 @echo Building $(patsubst _dir_%, %, $@) 
 $(MAKE) -C $(patsubst _dir_%, %, $@) all 
 
 
romfs: $(patsubst %, _romfs_%, $(KERNEL_MODULES)) 
$(patsubst %, _romfs_%, $(KERNEL_MODULES)): 
 $(MAKE) -C $(patsubst _romfs_%, %, $@) romfs 
 
 
clean: $(patsubst %, _clean_%, $(KERNEL_MODULES)) 
 $(RM) $(BUILD_DIR) 
$(patsubst %, _clean_%, $(KERNEL_MODULES)): 
 @echo 
 @echo Cleaning $(patsubst _dir_%, %, $@) 
 $(MAKE) -C $(patsubst _clean_%, %, $@) clean 
 
.PHONY:

3. ./netlink/netlink.c

/* 
 * netlink.c 
 * 
 * Created on: 2014 *  Author: cr 
 */ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include "usrlink.h" 
 
MODULE_LICENSE("Dual BSD/GPL"); 
MODULE_AUTHOR("MDAXIA"); 
 
struct sock *netlink_fd; 
 
 
static void netlink_to_user(int dest, void *buf, int len) 
{ 
 struct nlmsghdr *nl; 
 struct sk_buff *skb; 
 int size; 
 
 size = NLMSG_SPACE(len); 
 skb = alloc_skb(size, GFP_ATOMIC); 
 if(!skb || !buf) 
 { 
  printk(KERN_ALERT "netlink_to_user skb of buf null!\n"); 
  return; 
 } 
 nl = nlmsg_put(skb, 0, 0, 0, NLMSG_SPACE(len) - sizeof(struct nlmsghdr), 0); 
 NETLINK_CB(skb).pid = 0; 
 NETLINK_CB(skb).dst_group = 0; 
 
 memcpy(NLMSG_DATA(nl), buf, len); 
 nl->nlmsg_len = (len > 2) ? (len - 2):len; 
 
 netlink_unicast(netlink_fd, skb, dest, MSG_DONTWAIT); 
 printk(KERN_ALERT "K send packet success\n"); 
} 
 
static int process_hello_get(int dest, void *buf, int len) 
{ 
 printk(KERN_ALERT "In process_hello get!\n"); 
 memcpy(buf, "I known you !", 13); 
 netlink_to_user(dest, buf, 13); 
 return NET_OK; 
} 
 
static int process_hello_set(int dest, void *buf, int len) 
{ 
 printk(KERN_ALERT "In process_hello set! %s\n", (char *)buf); 
 memcpy(buf, "S known you !", 13); 
 netlink_to_user(dest, buf, 13); 
 return NET_OK; 
} 
 
 
static void netlink_process_packet(struct nlmsghdr *nl) 
{ 
 int ret; 
 
 switch(nl->nlmsg_type) 
 { 
 case HELLO_GET: 
  ret = process_hello_get(nl->nlmsg_pid, NLMSG_DATA(nl), nl->nlmsg_len); 
  break; 
 case HELLO_SET: 
  ret = process_hello_set(nl->nlmsg_pid, NLMSG_DATA(nl), nl->nlmsg_len); 
  break; 
 default:break; 
 } 
} 
 
static void netlink_recv_packet(struct sk_buff *__skb) 
{ 
 struct sk_buff *skb; 
 struct nlmsghdr *nlhdr; 
 
 skb = skb_get(__skb); 
 if(skb->len >= sizeof(struct nlmsghdr)) 
 { 
  nlhdr = (struct nlmsghdr *)skb->data; 
  if(nlhdr->nlmsg_len >= sizeof(struct nlmsghdr) && 
    __skb->len >= nlhdr->nlmsg_len) 
  { 
   netlink_process_packet(nlhdr); 
  } 
 } 
 else 
  printk(KERN_ALERT "Kernel receive msg length error!\n"); 
} 
 
static int __init netlink_init(void) 
{ 
 netlink_fd = netlink_kernel_create(&init_net, USER_NETLINK_CMD, 0, netlink_recv_packet, NULL, THIS_MODULE); 
 if(NULL == netlink_fd) 
 { 
  printk(KERN_ALERT "Init netlink!\n"); 
  return -1; 
 } 
 printk(KERN_ALERT "Init netlink success!\n"); 
 return 0; 
} 
 
static void __exit netlink_exit(void) 
{ 
 netlink_kernel_release(netlink_fd); 
 printk(KERN_ALERT "Exit netlink!\n"); 
} 
 
module_init(netlink_init); 
module_exit(netlink_exit);

4. ./netlink/usrlink.h

/* 
 * usrlink.h 
 * 
 * Created on: 2014騫?鏈?7鏃? *  Author: cr 
 */ 
#ifndef USRLINK_H_ 
#define USRLINK_H_ 
 
#define USER_NETLINK_CMD 25 
#define MAXMSGLEN   1024 
 
typedef enum error_e { 
 NET_ERROR, 
 NET_OK, 
 NET_PARAM, 
 NET_MEM, 
 NET_SOCK, 
} netlink_err; 
 
typedef enum module_e { 
 HELLO_CMD = 1, 
} netlink_module; 
 
typedef enum type_e { 
 HELLO_SET, 
 HELLO_GET, 
} netlink_type; 
 
#endif /* USRLINK_H_ */

5. ./netlink/Makefile

MOD_NAME := netlink 
 
$(MOD_NAME)-objs : netlink.o 
 
-include $(MODULES_ROOT_DIR)/rules.dir 
 
.PHONY:

6. 編譯方式

其中Makefile、rulers.dir 在Knetlink/下, netlink.c 、netlink.h 、Makefile在Knetlink/netlink/目錄下。 編譯時(shí)在Knetlink目錄下執(zhí)行Make即可

用戶程序

用戶程序的Makefile 這里就不放出了。 我是直接在eclipse下建的工程 自動(dòng)編譯的、...

1. netlink.c

/* 
 * usrlink.c 
 * 
 * Created on: 2014騫?鏈?7鏃? *  Author: cr 
 */ 
#include  
#include  
#include  
#include  
#include "usrlink.h" 
 
int netlink_sock_init(netlink_sock *netlink_s, int module, int protocol) 
{ 
 netlink_s->sock = socket(PF_NETLINK, SOCK_RAW, protocol); 
 if(netlink_s->sock < 0) 
  return NET_SOCK; 
 memset(&netlink_s->src, 0 ,sizeof(netlink_s->src)); 
 netlink_s->src.nl_family = AF_NETLINK; 
 netlink_s->src.nl_pid = module; 
 netlink_s->src.nl_groups = 0; 
 
 if(bind(netlink_s->sock, (struct sockaddr *)&netlink_s->src, sizeof(netlink_s->src)) < 0) 
  return NET_SOCK; 
 
 netlink_s->dest.nl_family = AF_NETLINK; 
 netlink_s->dest.nl_pid = 0; 
 netlink_s->dest.nl_groups = 0; 
 
 return NET_OK; 
} 
 
int netlink_send(netlink_sock *netlink_s, int type, char *sbuf, int slen, char *rbuf, int *rlen) 
{ 
 struct msghdr msg; 
 struct nlmsghdr *nlhdr = NULL; 
 struct iovec iov; 
 int ret; 
 
 nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAXMSGLEN)); 
 if(NULL == nlhdr) 
  return NET_MEM; 
 
 memcpy(NLMSG_DATA(nlhdr), sbuf, slen); 
 nlhdr->nlmsg_len = NLMSG_SPACE(slen); 
 nlhdr->nlmsg_pid = netlink_s->src.nl_pid; 
 nlhdr->nlmsg_type = type; 
 nlhdr->nlmsg_flags = 0; 
 
 iov.iov_base = (void *)nlhdr; 
 iov.iov_len = nlhdr->nlmsg_len; 
 
 msg.msg_name = (void *)&(netlink_s->dest); 
 msg.msg_namelen = sizeof(netlink_s->dest); 
 msg.msg_iov = &iov; 
 msg.msg_iovlen = 1; 
 
 ret = sendmsg(netlink_s->sock, &msg, 0); 
 if(ret < 0) 
 { 
  printf("Send fail\n"); 
  goto error; 
 } 
 ret = recvmsg(netlink_s->sock, &msg, 0); 
 if(ret < 0) 
 { 
  printf("Read fail\n"); 
  goto error; 
 } 
 memcpy(rbuf, NLMSG_DATA(nlhdr), nlhdr->nlmsg_len); 
 *rlen = nlhdr->nlmsg_len; 
 return NET_OK; 
 
error: 
 free(nlhdr); 
 return NET_SOCK; 
} 
 
int netlink_sock_deinit(netlink_sock *netlink_s) 
{ 
 close(netlink_s->sock); 
 memset(netlink_s, 0, sizeof(netlink_sock)); 
 return NET_OK; 
}

2. netlink.h

/* 
 * usrlink.h 
 * 
 * Created on: 2014 *  Author: cr 
 */ 
#include  
#include  
#include  
#include  
#include  
#ifndef USRLINK_H_ 
#define USRLINK_H_ 
 
#define USER_NETLINK_CMD 25 
#define MAXMSGLEN   1024 
 
typedef enum error_e { 
 NET_ERROR, 
 NET_OK, 
 NET_PARAM, 
 NET_MEM, 
 NET_SOCK, 
} netlink_err; 
 
typedef enum module_e { 
 HELLO_CMD = 1, 
} netlink_module; 
 
typedef enum type_e { 
 HELLO_SET, 
 HELLO_GET, 
} netlink_type; 
 
typedef struct usr_sock_h { 
 int sock; 
 struct sockaddr_nl dest; 
 struct sockaddr_nl src; 
} netlink_sock; 
 
int netlink_sock_init(netlink_sock *netlink_s, int module, int protocol); 
int netlink_sock_deinit(netlink_sock *netlink_s); 
int netlink_send(netlink_sock *netlink_s, int type, char *sbuf, int slen, char *rbuf, int *rlen); 
 
#endif /* USRLINK_H_ */

3. main.c

/* 
 * main.c 
 * 
 * Created on: 2014騫?鏈?7鏃? *  Author: cr 
 */ 
#include  
#include  
#include  
#include "usrlink.h" 
 
int parse_ret(int ret) 
{ 
 switch(ret) 
 { 
 case NET_OK: 
  return ret; 
 case NET_ERROR: 
  printf("error\n"); 
  goto exit_p; 
 case NET_MEM: 
  printf("Memory error\n"); 
  goto exit_p; 
 case NET_PARAM: 
  printf("Param error\n"); 
  goto exit_p; 
 case NET_SOCK: 
  printf("Socket error\n"); 
  goto exit_p; 
 default:break; 
 } 
exit_p: 
 return NET_ERROR; 
} 
 
void usage(void) 
{ 
 printf("Usage: Netlink -G \n\t-S \n"); 
} 
 
int main(int argc, char **argv) 
{ 
 netlink_sock h_sock; 
 char rbuf[1024]; 
 char sbuf[1024]; 
 int ret, type, slen = 0, rlen = 0; 
 
 ret = netlink_sock_init(&h_sock, HELLO_CMD, USER_NETLINK_CMD); 
 if(NET_OK != parse_ret(ret)) 
  goto exit_p; 
 
 bzero(&rbuf, sizeof(rbuf)); 
 bzero(&sbuf, sizeof(sbuf)); 
 if(argc < 3) 
 { 
  usage(); 
  goto exit_p; 
 } 
 if(!strncmp("-G", argv[1], 2)) 
  type = HELLO_GET; 
 else if(!strncmp("-S", argv[1], 2)) 
  type = HELLO_SET; 
 
 strcpy(sbuf, argv[2]); 
 slen = strlen(sbuf); 
 ret = netlink_send(&h_sock, type, sbuf, slen, rbuf, &rlen); 
 if(NET_OK != parse_ret(ret)) 
  goto exit_p; 
 
 if(rlen > 0) 
 { 
  rbuf[rlen] = '\0'; 
  printf("K rep [len = %d]:%s\n", rlen, rbuf); 
 } 
 printf("K[len = %d]: %s\n", rlen, rbuf); 
 
exit_p: 
 netlink_sock_deinit(&h_sock); 
 return 0; 
}

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“l(fā)inux中用戶程序同內(nèi)核通信的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!


網(wǎng)頁題目:linux中用戶程序同內(nèi)核通信的示例分析
鏈接地址:http://weahome.cn/article/jjpcpi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部