转自:http://blog.csdn.net/jk110333/article/details/8642261
 
用户态与内核态交互通信的方法不止一种,sockopt是比较方便的一个,写法也简单.
缺点就是使用 copy_from_user()/copy_to_user()完成内核和用户的通信, 效率其实不高, 多用在传递控制 选项 信息,不适合做大量的数据传输
 
用户态函数:
发送:int setsockopt ( int sockfd, int proto, int cmd, void *data, int datelen);
接收:int getsockopt(int sockfd, int proto, int cmd, void *data, int datalen)
第一个参数是socket描述符;
第二个参数proto是sock协议,IP RAW的就用SOL_SOCKET/SOL_IP等,TCP/UDP socket的可用SOL_SOCKET/SOL_IP/SOL_TCP/SOL_UDP等,即高层的socket是都可以使用低层socket的命令字 的,IPPROTO_IP;
第三个参数cmd是操作命令字,由自己定义;
第四个参数是数据缓冲区起始位置指针,set操作时是将缓冲区数据写入内核,get的时候是将内核中的数 据读入该缓冲区;
第五个参数数据长度
 
内核态函数
注册:nf_register_sockopt(struct nf_sockopt_ops *sockops)
解除:nf_unregister_sockopt(struct nf_sockopt_ops *sockops)
setsockopt():在内核调用kernel_setsockopt函数
 
结构体 nf_sockopt_ops test_sockops

static struct nf_sockopt_ops nso = { 
       .pf  = PF_INET,       // 协议族  
      .set_optmin = 常数,    // 定义最小set命令字  
       .set_optmax = 常数+N,  // 定义最大set命令字 
       .set  = recv_msg,   // 定义set处理函数 
       .get_optmin = 常数,    // 定义最小get命令字 
       .get_optmax = 常数+N,  // 定义最大get命令字 
       .get  = send_msg,   // 定义set处理函数 
};

其中命令字不能和内核已有的重复,宜大不宜小。命令字很重要,是用来做标识符的。而且用户态和内核态要定义的相同,
    #define SOCKET_OPS_BASE          128 
    #define SOCKET_OPS_SET       (SOCKET_OPS_BASE) 
    #define SOCKET_OPS_GET      (SOCKET_OPS_BASE)  
    #define SOCKET_OPS_MAX       (SOCKET_OPS_BASE + 1)

set/get处理函数是直接由用户空间的 set/getsockopt函数调用的。 setsockopt函数向内核写数据,用getsockopt向内核读数据。
另外set和get的处理函数的参数应该是这样的
int recv_msg(struct sock *sk, int cmd, void __user *user, unsigned int len)
int send_msg(struct sock *sk, int cmd, void __user *user, unsigned int *len)
 
附:

int kernel_setsockopt(struct socket *sock, int level, int optname,
char *optval, unsigned int optlen)
{
mm_segment_t oldfs = get_fs();
char __user *uoptval;
int err;

uoptval = (char __user __force *) optval;

set_fs(KERNEL_DS);
if (level == SOL_SOCKET)
err = sock_setsockopt(sock, level, optname, uoptval, optlen);
else
err = sock->ops->setsockopt(sock, level, optname, uoptval,
optlen);
set_fs(oldfs);
return err;
}

如果用户态level == SOL_SOCKET时,那么直接调用socket层统一的接口:sock_setsockopt,在socket层处理了,就像我之前说的那样,无论哪种协议,都在一个函数里面处理。
如果level不是SOL_SOCKET(也就是level是SOL_TCP/SOL_UDP,IPPROTO_IP),那么调用各自协议栈初始化时指向的setsockopt函数,11行的:sock->ops->setsockopt,

内核态与用户态通信 之 sockopt的更多相关文章

  1. Linux 内核态与用户态通信 netlink

    参考资料: https://blog.csdn.net/zqixiao_09/article/details/77131283 https://www.cnblogs.com/lopnor/p/615 ...

  2. 在linux系统中实现各项监控的关键技术(2)--内核态与用户态进程之间的通信netlink

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

  3. linux内核态和用户态的信号量

    在Linux的内核态和用户态都有信号量,使用也不同,简单记录一下. 1> 内核信号量,由内核控制路径使用.内核信号量是struct semaphore类型的对象,它在中定义struct sema ...

  4. Linux内核态、用户态简介与IntelCPU特权级别--Ring0-3

    一.现代操作系统的权限分离: 现代操作系统一般都至少分为内核态和用户态.一般应用程序通常运行于用户态,而当应用程序调用系统调用时候会执行内核代码,此时会处于内核态.一般的,应用程序是不能随便进入内核态 ...

  5. 操作系统基本概念(内核态与用户态、操作系统结构)-by sixleaves

    内核态与用户态(为什么存在这种机制.程序应处于哪个状态.如何判断当前所处状态.哪些功能需要内核态.如何实现这种机制) 1.首先我们应该思考清楚为什么会有内核态和用户态?(为什么存在这种机制) 因为计算 ...

  6. go语言学习--内核态和用户态(协程)

    go中的一个特点就是引入了相比于线程更加轻量级的协程(用户态的线程),那么什么是用户态和内核态呢? 一.什么是用户态和内核态 当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核 ...

  7. Linux内核态和用户态

    两张图说明Linux内核态和用户态之间的关系

  8. [OS] 内核态和用户态的区别

    http://blog.csdn.net/fatsandwich/article/details/2131707# http://jakielong.iteye.com/blog/771663 当一个 ...

  9. cpu与寄存器,内核态与用户态及如何切换

    cpu:相当于计算机的大脑负责运算和发送命令: 寄存器:寄存器是cpu当中的一个有限存储部件,cpu从内存调用数据时,寄存器会将从内存调用的数据进行更新在寄存器中以一个字或变量进行存储. 寄存器总共分 ...

  10. 【转】linux内核态和用户态的区别

    原文网址:http://www.mike.org.cn/articles/linux-kernel-mode-and-user-mode-distinction/ 内核态与用户态是操作系统的两种运行级 ...

随机推荐

  1. CTimeSpan

    要获取两个时间差,如两个CTime的时间差,可以使用MFC中的CTimeSpan类. CTime time1 = CTime::GetCurrentTime(); CTime time2 = CTim ...

  2. 关于指针*前后const代表的意思——记住一个口诀“左内右本”

    记住一个口诀“左内右本”:const出现在*的左边,则说明指针所指向的内容是常量const出现在*的右边,则说明指针本身是常量如果*左右两边都出现const,那么说明指针本事是常量,它所指向的内容也是 ...

  3. 牛客网_Go语言相关练习_判断&选择题(4)

    题目来源于牛客网 一.判断题 成员变量或者函数的首字母表示是否对外部可见. switch后面的声明语句和表达式语句都是可以选择的.例如: //可以什么都不加 switch: break; 错误指的是可 ...

  4. 用Physijs在场景中添加物理效果

    1.创建可用Physijs的基本Three.js场景 创建一个可用Physijs的Three.js场景非常简单,只要几个步骤即可.首先我们要包含正确的文件, 需要引入physi.js文件.实际模拟物理 ...

  5. 利用Google开源Java容器化工具Jib构建镜像

    转载:https://blog.csdn.net/u012562943/article/details/80995373 一.前言 容器的出现让Java开发人员比以往任何时候都更接近“编写一次,到处运 ...

  6. [Converge] Training Neural Networks

    CS231n Winter 2016: Lecture 5: Neural Networks Part 2 CS231n Winter 2016: Lecture 6: Neural Networks ...

  7. OpenGL——旋转的六边形(动画)

    代码: #include<iostream> #include <math.h> #include<Windows.h> #include <GL/glut. ...

  8. 使用JUnit测试预期异常

    开发人员常常使用单元测试来验证的一段儿代码的操作,很多时候单元测试可以检查抛出预期异常( expected exceptions)的代码.在Java语言中,JUnit是一套标准的单元测试方案,它提供了 ...

  9. Cordova 微信分享插件,安卓亲测可用

    Cordova 微信分享插件,安卓亲测可用,收藏 https://github.com/vilic/cordova-plugin-wechat

  10. Orleans学习总结(六)--应用篇

    上一篇Orleans学习总结(五)--监控篇,我们这篇来说说我们项目的应用   这是我们项目的结构图   我们分别来说下各个部分 1.Zookeeper作为集群基础,至少开5个,分别在不同的物理机上 ...