当前位置:
首页 >
Linux内核和应用层程序通信get/setsockopt示例
发布时间:2025/4/5
70
豆豆
生活随笔
收集整理的这篇文章主要介绍了
Linux内核和应用层程序通信get/setsockopt示例
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
最近开发一个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示例的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 股票佣金是什么时候收
- 下一篇: tcp/ip 协议栈Linux源码分析四