linux 内核与用户空间通信之netlink使用方法

来源:互联网 发布:淘宝客网站要多大空间 编辑:程序博客网 时间:2024/06/12 00:45
关于Netlink IPC方式的介绍,请参见http://blog.chinaunix.net/space.php?uid=14753126&do=blog&id=2978566
本文通过一个编程实例来更深入地了解netlink。
功能描述:
1. 本实例包含2个部分:内核模块和用户程序
2.用户程序通过netlink socket建立与kernel module连接,并向kernel module发送一条信息。
3.内核在接收到用户的信息后,向用户程序发送一条确认信息。

说明:对于不知如何编译内核模块以及用户程序的童鞋请google

内核模块代码(test_netlink_kmodule.c):
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/types.h>
  4. #include <linux/sched.h>
  5. #include <net/sock.h>
  6. #include <linux/netlink.h>

  7. #define NETLINK_TEST 17
  8. struct {
  9.     __u32 pid;
  10. }user_process;

  11. static struct sock *netlinkfd = NULL;

  12. int send_to_user(char *info) //发送到用户空间
  13. {
  14.     int size;
  15.     struct sk_buff *skb;
  16.     unsigned char *old_tail;
  17.     struct nlmsghdr *nlh; //报文头

  18.     int retval;

  19.     size = NLMSG_SPACE(strlen(info)); //报文大小
  20.     skb = alloc_skb(size, GFP_ATOMIC); //分配一个新的套接字缓存,使用GFP_ATOMIC标志进程不>会被置为睡眠

  21.     //初始化一个netlink消息首部
  22.     nlh = nlmsg_put(skb, 0, 0, 0, NLMSG_SPACE(strlen(info))-sizeof(struct nlmsghdr), 0); 
  23.     old_tail = skb->tail;
  24.     memcpy(NLMSG_DATA(nlh), info, strlen(info)); //填充数据区
  25.     nlh->nlmsg_len = skb->tail - old_tail; //设置消息长度

  26.     //设置控制字段
  27.     NETLINK_CB(skb).pid = 0;
  28.     NETLINK_CB(skb).dst_group = 0;

  29.     printk(KERN_DEBUG "[kernel space] skb->data:%s\n", (char *)NLMSG_DATA((struct nlmsghdr *)skb->data));

  30.     //发送数据
  31.     retval = netlink_unicast(netlinkfd, skb, user_process.pid, MSG_DONTWAIT);
  32.     printk(KERN_DEBUG "[kernel space] netlink_unicast return: %d\n", retval);
  33.     return 0;
  34. }

  35. void kernel_receive(struct sk_buff *__skb) //内核从用户空间接收数据
  36. {
  37.     struct sk_buff *skb;
  38.     struct nlmsghdr *nlh = NULL;

  39.     char *data = "This is eric's test message from kernel";

  40.     printk(KERN_DEBUG "[kernel space] begin kernel_receive\n");
  41.     skb = skb_get(__skb);

  42.     if(skb->len >= sizeof(struct nlmsghdr)){
  43.         nlh = (struct nlmsghdr *)skb->data;
  44.         if((nlh->nlmsg_len >= sizeof(struct nlmsghdr))
  45.             && (__skb->len >= nlh->nlmsg_len)){
  46.             user_process.pid = nlh->nlmsg_pid;
  47.             printk(KERN_DEBUG "[kernel space] data receive from user are:%s\n", (char *)NLMSG_DATA(nlh));
  48.             printk(KERN_DEBUG "[kernel space] user_pid:%d\n", user_process.pid);
  49.             send_to_user(data);
  50.         }
  51.     }else{
  52.         printk(KERN_DEBUG "[kernel space] data receive from user are:%s\n",(char *)NLMSG_DATA(nlmsg_hdr(__skb)));
  53.         send_to_user(data);
  54.     }

  55.     kfree_skb(skb);
  56. }

  57. int __init test_netlink_init(void)
  58. {

  59.     netlinkfd = netlink_kernel_create(&init_net, NETLINK_TEST, 0, kernel_receive, NULL, THIS_MODULE);
  60.     if(!netlinkfd){
  61.         printk(KERN_ERR "can not create a netlink socket\n");
  62.         return -1;
  63.     }
  64.     return 0;
  65. }

  66. void __exit test_netlink_exit(void)
  67. {
  68.     sock_release(netlinkfd->sk_socket);
  69.     printk(KERN_DEBUG "test_netlink_exit!!\n");
  70. }

  71. module_init(test_netlink_init);
  72. module_exit(test_netlink_exit);
  73. MODULE_LICENSE("GPL");
  74. MODULE_AUTHOR("eric.hu");
用户空间程序代码:user_sent.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <string.h>
  5. #include <linux/netlink.h>

  6. #define NETLINK_TEST 17
  7. #define MSG_LEN 100

  8. struct msg_to_kernel
  9. {
  10.     struct nlmsghdr hdr;
  11.     char data[MSG_LEN];
  12. };
  13. struct u_packet_info
  14. {
  15.     struct nlmsghdr hdr;
  16.     char msg[MSG_LEN];
  17. };

  18. int main(int argc, char* argv[]) 
  19. {
  20.     char *data = "This message is from eric's space";
  21.     //初始化
  22.     struct sockaddr_nl local;
  23.     struct sockaddr_nl kpeer;
  24.     int skfd, ret, kpeerlen = sizeof(struct sockaddr_nl);
  25.     struct nlmsghdr *message;
  26.     struct u_packet_info info;
  27.     char *retval;
  28.     message = (struct nlmsghdr *)malloc(1);

  29.     skfd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
  30.     if(skfd < 0){
  31.         printf("can not create a netlink socket\n");
  32.         return -1;
  33.     }
  34.     memset(&local, 0, sizeof(local));
  35.     local.nl_family = AF_NETLINK;
  36.     local.nl_pid = getpid();
  37.     local.nl_groups = 0;
  38.     if(bind(skfd, (struct sockaddr *)&local, sizeof(local)) != 0){
  39.         printf("bind() error\n");
  40.         return -1;
  41.     }
  42.     memset(&kpeer, 0, sizeof(kpeer));
  43.     kpeer.nl_family = AF_NETLINK;
  44.     kpeer.nl_pid = 0;
  45.     kpeer.nl_groups = 0;

  46.     memset(message, '\0', sizeof(struct nlmsghdr));
  47.     message->nlmsg_len = NLMSG_SPACE(strlen(data));
  48.     message->nlmsg_flags = 0;
  49.     message->nlmsg_type = 0;
  50.     message->nlmsg_seq = 0;
  51.     message->nlmsg_pid = local.nl_pid;

  52.     retval = memcpy(NLMSG_DATA(message), data, strlen(data));

  53.     printf("message sendto kernel are:%s, len:%d\n", (char *)NLMSG_DATA(message), message->nlmsg_len);
  54.     ret = sendto(skfd, message, message->nlmsg_len, 0,(struct sockaddr *)&kpeer, sizeof(kpeer));
  55.     if(!ret){
  56.         perror("send pid:");
  57.         exit(-1);
  58.     }

  59.     //接受内核态确认信息
  60.     ret = recvfrom(skfd, &info, sizeof(struct u_packet_info),0, (struct sockaddr*)&kpeer, &kpeerlen);
  61.     if(!ret){
  62.         perror("recv form kerner:");
  63.         exit(-1);
  64.     }

  65.     printf("message receive from kernel:%s\n",(char *)info.msg);
  66.     //内核和用户进行通信

  67.     close(skfd);
  68.     return 0;
  69. }
运行用户程序,输出结果如下:
  1. [root@FriendlyARM netlink]# ./user_sent
  2. message sendto kernel are:This message is from eric'space, len:52
  3. message receive from kernel:This is eric's test message from kernel
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 被强制消费后应怎么办? 当保安不发工资怎么办? 辅警改革流管员怎么办 退伍证上照片毁了怎么办 辅警年龄大了怎么办 交警2小时不出警怎么办 中暑发烧39度了怎么办 中暑头疼怎么办最快最有效 十五个月的宝宝拉肚子怎么办 中暑了头疼想吐怎么办 2周岁中暑了呕吐怎么办 容易中暑的人该怎么办 喷泡3m反光脏了怎么办 新摩托车被交警查到怎么办 写字楼保安夜班巡逻害怕怎么办 全民k歌歌曲删了怎么办 莲藕洞里的黑膜怎么办 鞋子后面的拉链磨脚怎么办 磨砂鞋尖踢掉皮怎么办 塔吊吊装过程中遇到障碍物怎么办 高速路上突然遇到障碍物怎么办 被不明物蛰了怎么办 喝酒后开车撞路政护栏怎么办 电脑过了质保期怎么办 电闸推不上去怎么办啊? 寝室的电闸不亮了怎么办 海绵城市改造只挖不修怎么办 怀孕一个月做了胸透怎么办 怀孕了照了胸透怎么办 刚怀孕照了胸透怎么办 怀孕进了ct室怎么办 消防稳压罐气囊压力不够怎么办 备孕期间拍了ct怎么办 晚上睡不好老做梦怎么办 零线和地线短路怎么办 火花塞拧的过紧怎么办 眼睛被电弧光灼伤怎么办 电脑模拟器微信附近人屏蔽了怎么办 美的电压锅漏气怎么办 电压力锅排气阀漏气怎么办 win10系统上不了网怎么办