没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
试读
37页
本系列文章包括两篇,它们文详细地介绍了 Linux 系统下用户空间与内核空间数据交换的九种方式,包括内核启动参数、模块参数与 sysfs、sysctl、系统调用、netlink、procfs、seq_file、debugfs和relayfs,并给出具体的例子帮助读者掌握这些技术的使用。 本文是该系列文章的第一篇,它介绍了内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink,并结合给出的例子程序详细地说明了它们如何使用。
资源推荐
资源详情
资源评论
本系列文章包括两篇,它们文详细地介绍了 Linux 系统下用户空间与内核空间数据交换的
九 种 方 式 , 包 括 内 核 启 动 参 数 、 模 块 参 数 与 sysfs 、 sysctl 、 系 统 调 用 、
netlink、procfs、seq_file、debugfs 和 relayfs,并给出具体的例子帮助读者掌握这些技术的
使用。
本文是该系列文章的第一篇,它介绍了内核启动参数、模块参数与 sysfs、sysctl、系统调用
和 netlink,并结合给出的例子程序详细地说明了它们如何使用。
一、引言
一般地,在使用虚拟内存技术的多任务系统上,内核和应用有不同的地址空间,因此,在
内核和应用之间以及在应用与应用之间进行数据交换需要专门的机制来实现,众所周知,
进程间通信(IPC)机制就是为实现应用与应用之间的数据交换而专门实现的,大部分读
者可能对进程间通信比较了解,但对应用与内核之间的数据交换机制可能了解甚少,本文
将详细介绍 Linux 系统下内核与应用进行数据交换的各种方式,包括内核启动参数、模块
参数与 sysfs、sysctl、系统调用、netlink、procfs、seq_file、debugfs 和 relayfs。
二、内核启动参数
Linux 提供了一种通过 bootloader 向其传输启动参数的功能,内核开发者可以通过这种方式
来向内核传输数据,从而控制内核启动行为。
通常的使用方式是,定义一个分析参数的函数,而后使用内核提供的宏 __setup 把它注册
到内核中,该宏定义在 linux/init.h 中,因此要使用它必须包含该头文件:
__setup("para_name=", parse_func)
para_name 为参数名,parse_func 为分析参数值的函数,它负责把该参数的值转换成相应的
内核变量的值并设置那个内核变量。内核为整数参数值的分析提供了函数 get_option 和
get_options,前者用于分析参数值为一个整数的情况,而后者用于分析参数值为逗号分割
的一系列整数的情况,对于参数值为字符串的情况,需要开发者自定义相应的分析函数。
在源代码包中的内核程序 kern-boot-params.c 说明了三种情况的使用。该程序列举了参数为
一个整数、逗号分割的整数串以及字符串三种情况,读者要想测试该程序,需要把该程序
拷贝到要使用的内核的源码目录树的一个目录下,为了避免与内核其他部分混淆,作者建
议在内核源码树的根目录下创建一个新目录,如 examples,然后把该程序拷贝到 examples
目录下并重新命名为 setup_example.c,并且为该目录创建一个 Makefile 文件:
obj-y = setup_example.o
Makefile 仅许这一行就足够了,然后需要修改源码树的根目录下的 Makefile 文件的一行,
把下面行
core-y := usr/
修改为
core-y := usr/ examples/
注意:如果读者创建的新目录和重新命名的文件名与上面不同,需要修改上面所说
Makefile 文件相应的位置。做完以上工作就可以按照内核构建步骤去构建新的内核,在构
建好内核并设置好 lilo 或 grub 为该内核的启动条目后,就可以启动该内核,然后使用 lilo
或 grub 的编辑功能为该内核的启动参数行增加如下参数串:
setup_example_int=1234 setup_example_int_array=100,200,300,400
setup_example_string=Thisisatest
当然,该参数串也可以直接写入到 lilo 或 grub 的配置文件中对应于该新内核的内核命令行
参数串中。读者可以使用其它参数值来测试该功能。
下面是作者系统上使用上面参数行的输出:
setup_example_int=1234
setup_example_int_array=100,200,300,400
setup_example_int_array includes 4 intergers
setup_example_string=Thisisatest
读者可以使用
dmesg | grep setup
来查看该程序的输出。
三、模块参数与 sysfs
内核子系统或设备驱动可以直接编译到内核,也可以编译成模块,如果编译到内核,可以
使用前一节介绍的方法通过内核启动参数来向它们传递参数,如果编译成模块,则可以通
过命令行在插入模块时传递参数,或者在运行时,通过 sysfs 来设置或读取模块数据。
Sysfs 是一个基于内存的文件系统,实际上它基于 ramfs,sysfs 提供了一种把内核数据结构,
它们的属性以及属性与数据结构的联系开放给用户态的方式,它与 kobject 子系统紧密地结
合在一起,因此内核开发者不需要直接使用它,而是内核的各个子系统使用它。用户要想
使用 sysfs 读取和设置内核参数,仅需装载 sysfs 就可以通过文件操作应用来读取和设置内
核通过 sysfs 开放给用户的各个参数:
$ mkdir -p /sysfs
$ mount -t sysfs sysfs /sysfs
注意,不要把 sysfs 和 sysctl 混淆,sysctl 是内核的一些控制参数,其目的是方便用户对内
核的行为进行控制,而 sysfs 仅仅是把内核的 kobject 对象的层次关系与属性开放给用户查
看,因此 sysfs 的绝大部分是只读的,模块作为一个 kobject 也被出口到 sysfs,模块参数则
是作为模块属性出口的,内核实现者为模块的使用提供了更灵活的方式,允许用户设置模
块参数在 sysfs 的可见性并允许用户在编写模块时设置这些参数在 sysfs 下的访问权限,然
后用户就可以通过 sysfs 来查看和设置模块参数,从而使得用户能在模块运行时控制模块行
为。
对于模块而言,声明为 static 的变量都可以通过命令行来设置,但要想在 sysfs 下可见,必
须通过宏 module_param 来显式声明,该宏有三个参数,第一个为参数名,即已经定义的变
量名,第二个参数则为变量类型,可用的类型有 byte, short, ushort, int, uint, long, ulong,
charp 和 bool 或 invbool,分别对应于 c 类型 char, short, unsigned short, int, unsigned int, long,
unsigned long, char * 和 int , 用 户 也 可 以 自 定 义 类 型 XXX ( 如 果 用 户 自 己 定 义 了
param_get_XXX,param_set_XXX 和 param_check_XXX)。该宏的第三个参数用于指定访
问权限,如果为 0,该参数将不出现在 sysfs 文件系统中,允许的访问权限为 S_IRUSR,
S_IWUSR,S_IRGRP,S_IWGRP,S_IROTH 和 S_IWOTH 的组合,它们分别对应于用户
读,用户写,用户组读,用户组写,其他用户读和其他用户写,因此用文件的访问权限设
置是一致的。
在源代码包中的内核模块 module-param-exam.c 是一个利用模块参数和 sysfs 来进行用户态
与内核态数据交互的例子。该模块有三个参数可以通过命令行设置,下面是作者系统上的
运行结果示例:
$ insmod ./module-param-exam.ko my_invisible_int=10 my_visible_int=20
mystring="Hello,World"
my_invisible_int = 10
my_visible_int = 20
mystring = 'Hello,World'
$ ls /sys/module/module_param_exam/parameters/
mystring my_visible_int
$ cat /sys/module/module_param_exam/parameters/mystring
Hello,World
$ cat /sys/module/module_param_exam/parameters/my_visible_int
20
$ echo 2000 > /sys/module/module_param_exam/parameters/my_visible_int
$ cat /sys/module/module_param_exam/parameters/my_visible_int
2000
$ echo "abc" > /sys/module/module_param_exam/parameters/mystring
$ cat /sys/module/module_param_exam/parameters/mystring
abc
$ rmmod module_param_exam
my_invisible_int = 10
my_visible_int = 2000
mystring = 'abc'
四、sysctl
Sysctl 是一种用户应用来设置和获得运行时内核的配置参数的一种有效方式,通过这种方
式,用户应用可以在内核运行的任何时刻来改变内核的配置参数,也可以在任何时候获得
内核的配置参数,通常,内核的这些配置参数也出现在 proc 文件系统的/proc/sys 目录下,
用户应用可以直接通过这个目录下的文件来实现内核配置的读写操作,例如,用户可以通
过
Cat /proc/sys/net/ipv4/ip_forward
来得知内核 IP 层是否允许转发 IP 包,用户可以通过
echo 1 > /proc/sys/net/ipv4/ip_forward
把内核 IP 层设置为允许转发 IP 包,即把该机器配置成一个路由器或网关。一般地,所有
的 Linux 发布也提供了一个系统工具 sysctl,它可以设置和读取内核的配置参数,但是该工
具依赖于 proc 文件系统,为了使用该工具,内核必须支持 proc 文件系统。下面是使用
sysctl 工具来获取和设置内核配置参数的例子:
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
$ sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
注 意 , 参 数 net.ipv4.ip_forward 实 际 被 转 换 到 对 应 的 proc 文
件/proc/sys/net/ipv4/ip_forward,选项 -w 表示设置该内核配置参数,没有选项表示读内核配
置参数,用户可以使用 sysctl -a 来读取所有的内核配置参数,对应更多的 sysctl 工具的信
息,请参考手册页 sysctl(8)。
但是 proc 文件系统对 sysctl 不是必须的,在没有 proc 文件系统的情况下,仍然可以,这时
需要使用内核提供的系统调用 sysctl 来实现对内核配置参数的设置和读取。
在源代码包中给出了一个实际例子程序,它说明了如何在内核和用户态使用 sysctl。头文件
sysctl-exam.h 定义了 sysctl 条目 ID,用户态应用和内核模块需要这些 ID 来操作和注册
sysctl 条目。内核模块在文件 sysctl-exam-kern.c 中实现,在该内核模块中,每一个 sysctl 条
目对应一个 struct ctl_table 结构,该结构定义了要注册的 sysctl 条目的 ID(字段 ctl_name),
在 proc 下的名称(字段 procname),对应的内核变量(字段 data,注意该该字段的赋值
必须是指针),条目允许的最大长度(字段 maxlen,它主要用于字符串内核变量,以便在
对该条目设置时,对超过该最大长度的字符串截掉后面超长的部分),条目在 proc 文件系
统下的访问权限(字段 mode),在通过 proc 设置时的处理函数(字段 proc_handler,对
剩余36页未读,继续阅读
资源评论
- 丶随心2021-05-06里面没有完整示例代码,只有文档描述,跟部分函数数据结构描述。
newnewman80
- 粉丝: 315
- 资源: 124
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 407000001.fasset
- J-20240402998-HTE-HTE-2947110DA-D3_整车运动控制器-电压渐变(缓升缓降)-检测报告-XS-汽车及零部件检测中心.pdf.crdownload
- Excel表格VBA-获取文件夹内所有文件路径.zip
- 文件移动.zip
- 反射源代码,源代码,源代码,源代码
- CAJViewer 9.0_x64-setup.exe
- servant C++语言框架rpc的源码实现 tools C++语言框架IDL工具的源码实现 util C++语言.7z
- 使用pyqt创建一个登录具有动态背景的登陆界面
- 实验名称 调幅波信号的解调
- 实验名称 振幅调制器(利用乘法器)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功