最近开发一个realtek网卡配置程序,基于realtek提供的一套配置程序代码开发,分析代码的时候发现用户层和驱动之间传递消息是使用的是setsockopt、getsockopt,这个对我来说比较新鲜,以前见到的大都是netlink、proc等等,使用这种方式特别简单,应用层这边只需要创建套接字,而内核层只需要注册一个struct nf_sockopt_ops 结构体就可以了,这种方式以后可能会用到,先记录一下:

getsockopt, setsockopt声明:

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval,socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);socketfd : 套接字
level : 类型,可以是SOL_SOCKET,IPPROTO_IP, IPPROTO_IPV6
optname : 操作类型,内核部分和应用部分关于操作类型定义一直,使用的时候不要和系统混用
optval : 选项值
optLen : 选项长度
成功返回0,失败返回-1并置errno

内核需要定义的结构体:

/* 内核部分定义结构体 */
struct nf_sockopt_ops {struct list_head list;u_int8_t pf; /* 协议族, AF_INET | AF_INET6 *//* Non-inclusive ranges: use 0/0/NULL to never get called. */int set_optmin;    /* SET类操作类型最小值 */int set_optmax;    /* SET类操作类型最大值 */int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len); /* SET回调处理函数 */int get_optmin;    /* GET类操作类型最小值 */int get_optmax;    /* GET类操作类型最大值 */int (*get)(struct sock *sk, int optval, void __user *user, int *len); /* SET回调处理函数 *//* Use the module struct to lock set/get code in place */struct module *owner;
};

结构体定义好后内核层做好相应的处理函数就可以了,用例:

内核和应用层公共头文件:

sockopt_test.h

#ifndef __SOCKOPT_TEST_H_
#define __SOCKOPT_TEST_H_#define SOCKOPT_BASE                 (10240)
#define SOCKOPT_SET_MIN              ((SOCKOPT_BASE) + 1)
#define SOCKOPT_SET_BUFFER                ((SOCKOPT_BASE) + 1)
#define SOCKOPT_SET_MAX              ((SOCKOPT_BASE) + 2)#define SOCKOPT_GET_MIN              ((SOCKOPT_BASE) + 1)
#define SOCKOPT_GET_BUFFER                ((SOCKOPT_BASE) + 1)
#define SOCKOPT_GET_MAX              ((SOCKOPT_BASE) + 2)#endif

内核实现:sockopt_test.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include "sockopt_test.h"#define BUFFER_LEN_MAX 1024
static char buffer[BUFFER_LEN_MAX];/* setsockopt 回调处理函数 */
int setsockopt_handler(struct sock *sk, int optval, void __user *user, unsigned int len)
{switch(optval){case SOCKOPT_SET_BUFFER:if ( copy_from_user((void*)&buffer, user, len) != 0 ) {return -EFAULT;}break;default:printk(KERN_INFO "invalid setsockopt opt : %d\n", optval);return -EFAULT;}printk(KERN_INFO "buffer[]: %s\n", buffer);return 0;
}/* getsockopt 回调处理函数 */
int getsockopt_handler(struct sock *sk, int optval, void __user *user, int *len)
{unsigned int cpy_len;cpy_len = *len > BUFFER_LEN_MAX ? BUFFER_LEN_MAX : *len;switch(optval){case SOCKOPT_GET_BUFFER:if(copy_to_user(user, (void*)&buffer[0], cpy_len) != 0) {printk(KERN_INFO "getsockopt_handler fail \n");return -EFAULT;}break;default:printk(KERN_INFO "unrecognized getsockopt optvalue : %d\n", optval);return -EFAULT;}return 0;
}/* 定义nf_sockopt_ops结构体 */
static struct nf_sockopt_ops sockopt_ops_test =
{.pf                     = PF_INET,.set_optmin             = SOCKOPT_SET_MIN,.set_optmax             = SOCKOPT_SET_MAX,.set                    = setsockopt_handler,.get_optmin             = SOCKOPT_GET_MIN,.get_optmax             = SOCKOPT_GET_MAX,.get                    = getsockopt_handler,
};static __init int sockopt_test_init(void)
{int result;/* 注册sockopt */result = nf_register_sockopt(&sockopt_ops_test);if(result != 0) {printk("register sockopt error!\n");}printk("sockopt_test register success !\n");return 0;
}static __exit void sockopt_test_exit(void)
{/* 注销sockopt */nf_unregister_sockopt(&sockopt_ops_test);printk("sockopt_test unregister\n");
}module_init(sockopt_test_init);
module_exit(sockopt_test_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stone");

应用层:

sockopt_user.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "sockopt_test.h"#define USAGE "./sockopt get \n"  \"./sockopt set buffer \n"#define BUFFER_LEN_MAX 1024
static char buffer[BUFFER_LEN_MAX];static int
getsockopt_handler(void)
{int fd, ret, size;size = sizeof(buffer);memset(buffer, '\0', size);fd = socket(PF_INET, SOCK_DGRAM, 0);if(fd == -1) {printf("socket error, errno : %d\n", errno);return -1;}ret = getsockopt(fd, IPPROTO_IP, SOCKOPT_GET_BUFFER, buffer, &size);if (ret == -1){printf("getsockopt fail, errno : %d\n", errno);}else{printf("getsockopt return buffer : %s\n", buffer);}close(fd);return 0;
}static int
setsockopt_handler(char *arg)
{int fd, ret, cpy_len;unsigned int size;size = sizeof(buffer);cpy_len = size > strlen(arg) ? strlen(arg) : size;        memset(buffer, '\0', size);memcpy(buffer, arg, cpy_len);fd = socket(PF_INET, SOCK_DGRAM, 0);if(fd == -1) {printf("socket error, errno : %d\n", errno);return -1;}ret = setsockopt(fd, IPPROTO_IP, SOCKOPT_SET_BUFFER, buffer, size);if (ret == -1){printf("setsockopt fail, errno : %d\n", errno);}close(fd);return 0;
}int
main(int argc, char **argv)
{int direction;int index;int value = 9;if(argc < 2) {                goto FAIL;}if(strcmp(argv[1], "get") == 0) {return getsockopt_handler();} else if(strcmp(argv[1], "set") == 0) {if (argc != 3){goto FAIL;}return setsockopt_handler(argv[2]);} FAIL:printf(USAGE);exit(EXIT_FAILURE);
}

运行示例:

参考资料:

1.man getsockopt,  https://linux.die.net/man/2/getsockopt

2. Linux Kernel 学习笔记17:内核与用户层通信之sockopt

https://blog.csdn.net/stone8761/article/details/76049865#commentBox

Linux内核和应用层程序通信get/setsockopt示例相关推荐

  1. Linux内核态之间进程通信,Linux 系统内核空间与用户空间通信的实现与分析[转载]...

    [https://www.ibm.com/developerworks/cn/linux/l-netlink/index.html] 多数的 Linux 内核态程序都需要和用户空间的进程交换数据,但 ...

  2. linux内核更新/修补程序,Ubuntu 18.04.3 LTS无需重启即可轻松修补Linux内核

    Ubuntu 18.04.3 LTS本月早些时候推出了更新的内核和图形堆栈,以及所有最新的软件包更新和增强的Livepatch集成. 由Ubuntu 19.04(Disco Dingo)的Linux ...

  3. Linux内核态之间进程通信,内核态和用户态通信(二)--实现

    本文主要使用netlink套接字实现中断环境与用户态进程通信. 系统环境:基于linux 2.6.32.27 和 linux 3.16.36 Linux内核态和用户态进程通信方法的提出和实现 用户上下 ...

  4. linux内核参数的程序,技巧-Linux内核参数调整办法

    ulimit设置 ulimit -n 要调整为100000甚至更大. 命令行下执行 ulimit -n 100000即可修改.如果不能修改,需要设置 /etc/security/limits.conf ...

  5. Linux内核:IO设备通信的控制方式

    IO设备与主机(CPU.内存)之间的通信不是直接的,而是通过设备控制器,设备控制器是IO设备和主机之间的中介.IO设备和进程之间的数据传送方式主要有4种: 1.程序控制方式:又被称为"忙等& ...

  6. QT接收Linux内核,QT界面程序经过网路与普通的linux应用程序进行数据传送的情况...

    有时候会遇到QT界面程序经过网路与普通的linux应用程序进行数据传送的情况:(UDP协议,非TCP协议) 个人感觉比管道.共享内存.信号量.消息队列好用 Qt udp_client 1.我们新建Qt ...

  7. linux内核之netlink通信

    Linux内核(04)之netlink通信 Author:Onceday Date:2023年1月3日 漫漫长路,才刚刚开始- 参考文档: netlink 机制 binarydady 阿里云开发者社区 ...

  8. linux怎么定义程序执行有限级别,linux 内核是什么?

    一:linux系统如何构成的?User space:User Applications and GNU C library (glibc)kernel space:System Call interf ...

  9. Linux内核深入理解系统调用(2):vsyscall 和 vDSO 以及程序是如何运行的(execve)

    Linux内核深入理解系统调用(2) vsyscall 和 vDSO 以及程序是如何运行的(execve) rtoax 2021年3月 1. vsyscalls 和 vDSO 这是讲解 Linux 内 ...

最新文章

  1. 【转载】c#多线程使用webbrowser控件
  2. 上班后咋防控?分享一份指南
  3. java encode in ansi_Java应用中的编码问题
  4. notify()唤醒线程,不会立即释放锁对象,需要等到当前同步代码块都执行完后才能释放锁对象
  5. 欢乐纪中A组赛【2019.8.9】
  6. Spring注解@ConfigurationPropertie
  7. 学生HTML5今后的打算,今后我打算小学生日记
  8. java 象限分析_用四种象限分析你(未来的人生走向)
  9. 一个事务复制的bug--更新丢失 续
  10. 神经网络——单层感知器
  11. idea切换工作空间_IDEA中如何在一个工作空间中管理多个项目
  12. 前端性能优化:前端接口缓存方案
  13. ddwrt(ddwrt和openwrt哪个好)
  14. 20220525商汤算法岗实习面试经历
  15. python/appium实现华为应用商城app界面上下滑动打开关闭通知栏等功能
  16. 机器学习——决策树与随机森林
  17. 读曾仕强《管理的方与圆》笔记三
  18. Python Pytorch
  19. 用php写水仙花及思路,php水仙花数
  20. word2010打开97-03格式的word文件失败的解决方法

热门文章

  1. Sublime Text 3在ubuntu12.10下无法中文输入的解决方案
  2. MSSQLSERVER数据库- SQL交叉表
  3. JAVA socket编程实例 转载
  4. 用神经网络计算甲醛CH2O和亚硝酸HNO2的化学键的键能
  5. mysql table combine_Mysql系列-性能优化神器EXPLAIN使用介绍及分析
  6. lmbs PHP,PHP的GD2函数创建折线图源码示例
  7. C++中类的多态与虚函数的使用(转)
  8. 【PC工具】PhotoScape简单绿色功能强大的照片编辑器
  9. 【蚁群路径规划】基于MATLAB的蚁群算法的二维路径规划
  10. ARP协议及ARP欺骗详解