千家信息网

linux中用户程序同内核通信的示例分析

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍了linux中用户程序同内核通信的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。简介linux下用户程序同内核
千家信息网最后更新 2026年11月01日linux中用户程序同内核通信的示例分析

这篇文章主要介绍了linux中用户程序同内核通信的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

简介

linux下用户程序同内核通信的方式一般有ioctl, proc文件系统,剩下一个就是Netlink套接字了。 这里先介绍下netlink。

Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 netlink。

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则需要专门的培训才能使用。

下面这两部分代码主要的目的是用netlink机制实现用户程序和内核的通信。 具体就是用户程序执行./netlink -S [我是参数] 或./netlink -G 时,内核会返回"S know you!" 和"I know you!" 这两种字符串, 然后输出。 内核和用户程序均加有打印。

内核模块

1. Makefile依赖的编译规则 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 #这行是为了取出系统下内核的目录(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/目录下。 编译时在Knetlink目录下执行Make即可

用户程序

用户程序的Makefile 这里就不放出了。 我是直接在eclipse下建的工程 自动编译的、...

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; }

感谢你能够认真阅读完这篇文章,希望小编分享的"linux中用户程序同内核通信的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

内核 用户 系统 应用 程序 通信 消息 编译 文件 机制 模块 方式 目录 篇文章 部分 事件 数据 示例 分析 混乱 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技图片 厦门中拓互联网络科技有限公司 鸠鸠互联网科技 易互联网科技有限公司 智慧科技互联网 天下捷融互联网科技 湖南洣水互联网科技有限公司扣款 互联网科技与管理 千方科技属于互联网企业吗 哈尔滨屹滨互联网科技有限公司 佛山市拉法互联网科技有限公司 信承诺互联网科技有限公司 萌小萌互联网科技河南有限公司 容联科技互联网电商 互联网金融运营模式中的金融科技 北京互联网科技类企业分布 科技互联网经济论坛 安徽九吞吴互联网科技有限公司 互联网科技企业文化 小牛互联网科技有限公司地址 互联网与科技 美国互联网保险保险科技 互联网科技有限公司经营范围 上海喔噻互联网科技 互联网科技美容 茂名市互联网科技产业园 爱医互联网络科技 好易买互联网科技 盐城市攀科互联网科技有限公司 北京瑞云互联网科技有限公司
0