当前位置: 首页 > news >正文

Linux网络技术学习(四)—— 用户空间与内核的接口

文章目录

    • 概述
    • 两个虚拟文件系统:procfs和sys
    • 应用层接口
    • procfs与sysctl使用分析
      • procfs
        • 以ARP协议注册为例
      • systcl:目录/proc/sys
        • ctl_table结构体实例举例
    • 核心网络文件和目录
      • ifconfig命令使用ioctl与内核通信。


概述

内核通过各种不同的接口把内部信息输出到用户空间。


两个虚拟文件系统:procfs和sys

(1) procfs(/proc 文件系统)
这是一个虚拟文件系统,通常是挂载(mount)在/proc,允许内核以文件的形式向用户空间输出内部信息。
这些文件并没有实际存在于磁盘中,但是可以通过cat(查看)或> shell (写入)文件。这些文件可以像真实文件一样指定其访问权限。
内核组件可以说明任何一个文件可由谁读取或写入。
目录不能被写入。(用户不能把文件或目录添加到/proc中的任何目录)

内核配置

make ARCH=arm64 menuconfig
    -> File system
        -> Pseudo filesystems
            -> [*] /proc file system support 

(2) sysctl(/proc/sys目录)
此接口允许用户空间读取或修改内核变量的值。(不能用此接口对内核每个变量进行修改操作)
在用户空间中,你可以用两种方式访问sysctl输出的变量
第一种,sysctl系统调用
第二种,procfs。当内核支持procfs时,会在/proc中添加一个特殊目录(/proc/sys)。为每个由sysctl所输出的内核变量引入一个文件。
此命令通过写入/proc/sys与内核对话

内核配置

make ARCH=arm64 menuconfig
    -> File system
        -> Pseudo filesystems
            -> [*]   Sysctl support (/proc/sys)

(3) sysfs(/sys文件系统)
sysfs用以干净并且有组织的方式输出很多信息。sysctl所输出的部分信息可以移植到sysfs。

内核配置

make ARCH=arm64 menuconfig
    -> File system
        -> Pseudo filesystems
            -> -*- sysfs file system support 

应用层接口

应用层使用下列接口把命令传给内核,配置某事或者去掉某些配置内容:
ioctl 系统调用
ioctl(输入/输出控制)系统调用操作的对象是一个文件,通常是用于实现特殊设备所需但标准文件系统没有提供的操作。
可以把socket系统调用的套接字描述符传给ioctl,这就是网络代码使用ioctl的方法。
使用ifconfig和route都调用这个函数访问。

Netlink 套接字(socket)
这是网络应用程序与内核通信时最新的首选机制。IPROUTE2包中大多数命令都是用此接口进行配置。


procfs与sysctl使用分析

procfs和sysctl都是输出内核内部信息。procfs主要输出只读数据;sysctl信息使用超级用户可以写入的。
sysctl输出:简单的内核变量或数据结构相关联的一些文件;
procfs输出:复杂的数据结构并且需要特殊格式时使用。

procfs

1、大多数网络功能在其初始化时都会在/proc中注册一个或多个文件。用户在读取该文件时,会引起内核间接运行一组内核函数,以返回某种输出内容。
2、网络代码所注册的文件位于/proc/net/
3、/proc中的目录可以使用proc_mkdir创建。/proc/net中的文件可以使用定义在<include/linux/proc_fs.h>中的proc_create_net和remove_proc_entry注册和除名。

以ARP协议注册为例

static struct pernet_operations arp_net_ops = {
    .init = arp_net_init,
    .exit = arp_net_exit,
};

static int __init arp_proc_init(void)
{
    return register_pernet_subsys(&arp_net_ops);
}

register_pernet_subsys会将arp_net_ops加入ops->list链表中。系统初始化的时候执行链表上结构体中的init函数

static const struct seq_operations arp_seq_ops = {                  // arp协议操作函数
    .start  = arp_seq_start,
    .next   = neigh_seq_next,
    .stop   = neigh_seq_stop,
    .show   = arp_seq_show,
};

// 文件路径:fs/proc/proc_net.c
// #define proc_create_net(name, mode, parent, state_size, ops)  proc_create_net_data(name, mode, parent, state_size, ops, NULL)
// struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct seq_operations *ops, unsigned int state_size, void *data)
// 传入参数:名字,权限,

static int __net_init arp_net_init(struct net *net)                    // 在proc中建立arp接口
{
    if (!proc_create_net("arp", 0444, net->proc_net, &arp_seq_ops,
            sizeof(struct neigh_seq_state)))
        return -ENOMEM;
    return 0;
}

static void __net_exit arp_net_exit(struct net *net)
{
    remove_proc_entry("arp", net->proc_net);                             // 在proc中删除arp接口
}

用户对节点的操作相当于对arp_seq_ops结构体的调用。

systcl:目录/proc/sys

1、用户在/proc/sys看到的一个文件,实际上是内核变量。
2、在/proc/sys里以组件的来划分变量的所处的位置。例如:在/proc/sys/net/ipv4中可以找见与IPv4相关的文件。
3、访问权限。例如,一个文件可以由任何人读,但只能由超级用户修改。
4、输出到/proc/sys中的变量内容可以借助相关文件进行读写,或直接用sysctl系统调用。

/proc/sys中的文件和目录都是以ctl_table结构体定义的。ctl_table结构的注册和除名是通过在<kernel/sysctl.c>中的register_sysctl_table和unregister_sysctl_table函数实现。

static struct ctl_table sysctl_base_table[] = {
    {
        .procname   = "kernel",
        .mode       = 0555,
        .child      = kern_table,                   // 指向另一个ctl_table实体,这个实体列表的头元素
    },
    {
        .procname   = "vm",
        .mode       = 0555,
        .child      = vm_table,
    },
    {
        .procname   = "fs",
        .mode       = 0555,
        .child      = fs_table,
    },
    {
        .procname   = "debug",
        .mode       = 0555,
        .child      = debug_table,
    },
    {
        .procname   = "dev",
        .mode       = 0555,
        .child      = dev_table,
    },
    { }
};

int __init sysctl_init(void)
{
    struct ctl_table_header *hdr;

    hdr = register_sysctl_table(sysctl_base_table);
    kmemleak_not_leak(hdr);
    return 0;
}

解析下ctl_table结构体成员

struct ctl_table 
{
    const char *procname;       // 在/proc/sys中所用的文件名
    void *data;
    int maxlen;                 // 输出内核变量的尺寸大小
    umode_t mode;               // 分配给/proc/sys中相关联的文件或目录的访问权限
    struct ctl_table *child;    // 用于建立目录与文件之间的父子关系
    proc_handler *proc_handler; // 当在/proc/sys中读取或写入一个文件时,完成读取或写入操作的函数。所有与文件相关联的ctl_instances都必须由pro_handler初始化
    struct ctl_table_poll *poll;
    // strategy 用sysctl系统调用访问/proc/sys中的文件时被调用(rk3568平台没有此成员,其他平台需注意)
    void *extra1;
    void *extra2;              // 两个可选的参数,用于定义变量的最小值min和最大值max
} __randomize_layout;

根据与文件相关联的变量种类而定,proc_handler和strategy初始化不同。
所有变量的proc_handler和strategy初始化,定义<kernel/sysctl.c>中
在这里插入图片描述

ctl_table结构体实例举例

/proc/sys/net/ipv4/conf/eth0/accept_local文件ctl_table结构体定义在<net/ipv4/devinet.c>

    { 
        .procname   = "accept_local", 
        .data       = ipv4_devconf.data + \                   // 指向accept_local数值
                  IPV4_DEVCONF_ ## attr - 1, \
        .maxlen     = sizeof(int), \
        .mode       = 0644, \
        .proc_handler   = devinet_conf_proc, \
        .extra1     = &ipv4_devconf, \
    }

上面是一个accept_local文件的定义。文件名称为accept_local,通过accept_local文件输出的值为ipv4_devconf指针所指向的内核accept_local数值。文件的权限为0644。proc_handler初始化为devinet_conf_proc
通过register_net_sysctl创建,最总调用__register_sysctl_table

// net/ipv4/devinet.c   __devinet_sysctl_register
// 每个文件下所有变量文件模块定义赋值
for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
    t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
    t->devinet_vars[i].extra1 = p;
    t->devinet_vars[i].extra2 = net;
}

// 以函数传进来的dev_name创建文件,上面例子就是net/ipv4/conf/eth0/
snprintf(path, sizeof(path), "net/ipv4/conf/%s", dev_name);
t->sysctl_header = register_net_sysctl(net, path, t->devinet_vars);          // t->devinet_vars为树的根

__register_sysctl_table的输入路径不包括/proc/sys。传入的参数ctl_table却会添加到/proc/sys文件下面的对应目录下?这是因为所有的插入都针对/proc/sys目录进行。
如果想要把一个文件注册到/proc/sys的子目录,就要建一棵树(多个文件可以由child字段链接的ctl_table实体)。当数的节点未存在就会被创建。
参考文献中有个实例
在这里插入图片描述
register_sysctl_table接收的时scsi_root_table,也就是这段代码里的根
在这里插入图片描述


核心网络文件和目录

在/proc/sys中由网络代码所使用的主要目录。

ifconfig命令使用ioctl与内核通信。

当系统管理输入像ifconfig eth0 mtu 1250这样的命令,用以改变接口eth0的MTU时,ifconfig会打开一个套接字,从系统管理员那接收的信息初始化一个本地数据结构体,然后以ioctl调用传送给内核。SIOCSIFMTU是命令标识符

struct ifreq data;
fd = socket(PF_INET,SOCK_DGRAM,0);
err = ioctl(fd,SIOCSIFMTU,&data);

内核会在几个不同地方处理ioctl命令。将由sock_ioctl分配
在这里插入图片描述

ioctl命令的名称解析
ADD ,表示要添加什么
RT , 表示要添加的是一条路由
G , 取得
S ,设置

例:SIOCADDRT (添加路由);SIOCSIFMTU(设定(S)接口(IF)的最大传输单元(MTU))
网络用的命令列在<include/uapi/linux/sockios.h>中。设备驱动程序可以用代码定义新的(私有)命令。范围介于SIOCPROTOPRIVATE和SIOCPROTOPRIVATE+15之间

相关文章:

  • Django--ORM 多表查询
  • pytest 运行方式、常用参数、前后置条件
  • MySQL-1-SQL讲解
  • 数据结构与算法之美读书笔记15
  • msf辅助模块详细操作
  • 【移动端网页特效】02-移动端轮播图(原生JS)
  • 神经网络(十二)卷积神经网络DLC
  • vue3.x 组件间传参
  • Tomcat域名访问文件出现访问不到的问题
  • BATJ 互联网公司面试必问知识点:Spring 全家桶全解,java 分布式框架技术方案
  • RabbitMQ(一)消息队列
  • Pycharm打开时一直加载中?解决办法来了~
  • Spring Security 如何防止 Session Fixation 攻击
  • 【C++基础】1. 基本使用
  • H3C交换机如何查环路
  • EOS是什么
  • gf框架之分页模块(五) - 自定义分页
  • Javascript Math对象和Date对象常用方法详解
  • JAVA多线程机制解析-volatilesynchronized
  • Linux中的硬链接与软链接
  • Theano - 导数
  • v-if和v-for连用出现的问题
  • Vue UI框架库开发介绍
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 基于遗传算法的优化问题求解
  • 简单易用的leetcode开发测试工具(npm)
  • 前端临床手札——文件上传
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 提醒我喝水chrome插件开发指南
  • 写给高年级小学生看的《Bash 指南》
  • 移动端唤起键盘时取消position:fixed定位
  • ​力扣解法汇总946-验证栈序列
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • #14vue3生成表单并跳转到外部地址的方式
  • (9)目标检测_SSD的原理
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (原創) 未来三学期想要修的课 (日記)
  • (转) Android中ViewStub组件使用
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (转)scrum常见工具列表
  • (转载)(官方)UE4--图像编程----着色器开发
  • ***详解账号泄露:全球约1亿用户已泄露
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .Net8 Blazor 尝鲜
  • .NET多线程执行函数
  • .net连接oracle数据库
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • .考试倒计时43天!来提分啦!
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...
  • @RestControllerAdvice异常统一处理类失效原因
  • @拔赤:Web前端开发十日谈
  • [ 数据结构 - C++]红黑树RBTree