本文首发于我的公众号Linux云估算网路(id:cloud_dev),专注于干货分享,号内有10T书籍和视频资源,后台回复「1024」即可申领,欢迎你们关注,二维码文末可以扫。
Linux用户态和内核态因为CPU权限的限制,通讯并不像想像中的使用进程间通讯方法这么简单,明天这篇文章就来瞧瞧Linux用户态和内核态到底有什么通讯方法。
我们平时在写代码时,通常是在用户空间,通过系统调用函数来访问内核空间,这是最常用的一种用户态和内核态通讯的形式。(关于Linux用户态和内核态可以参考xx)
除此之外,还有以下四种形式:
procfs(/proc)
procfs是进程文件系统的简写,它本质上是一个伪文件系统,为何说是伪文件系统呢?由于它不占用外部储存空间,只是占用少量的显存,一般是挂载在/proc目录下。
我们在该目录下看见的一个文件,实际上是一个内核变量。内核就是通过这个目录,以文件的方式诠释自己的内部信息,相当于/proc目录为用户态和内核态之间的交互搭建了一个桥梁,用户态读写/proc下的文件,就是读写内核相关的配置参数。
例如常见的/proc/cpuinfo、/proc/meminfo和/proc/net就分别提供了CPU、内存、网络的相关参数。除此之外,还有好多的参数,如下所示:
root@ubuntu:~# ls /proc/
1 1143 1345 1447 2 2292 29 331 393 44 63 70 76 acpi diskstats irq locks sched_debug sysvipc zoneinfo
10 1145 1357 148 20 23 290 332 396 442 64 7019 77 asound dma kallsyms mdstat schedstat thread-self
1042 1149 1361 149 2084 2425 291 34 398 45 65 7029 8 buddyinfo driver kcore meminfo scsi timer_list
1044 1150 1363 15 2087 25 3 3455 413 46 66 7079 83 bus execdomains keys misc self timer_stats
1046 1151 1371 16 2090 256 30 35 418 47 6600 7080 884 cgroups fb key-users modules slabinfo tty
1048 1153 1372 17 21 26 302 36 419 5 67 71 9 cmdline filesystems kmsg mounts softirqs uptime
11 1190 1390 18 22 27 31 37 420 518 6749 72 96 consoles fs kpagecgroup mtrr stat version
1126 12 143 182 2214 28 32 373 421 524 68 73 97 cpuinfo interrupts kpagecount net swaps version_signature
1137 1252 1434 184 2215 280 327 38 422 525 69 74 98 crypto iomem kpageflags pagetypeinfo sys vmallocinfo
1141 13 144 190 2262 281 33 39 425 5940 7 75 985 devices ioports loadavg partitions sysrq-trigger vmstat
可以看见,这儿面有好多的数字表示的文件,这种显然是当前系统运行的进程文件,数字表示进程号(PID),每位文件包含该进程所有的配置信息,包括进程状态、文件描述符、内存映射等等,我们可以看下:
root@ubuntu:~# ls /proc/1/
attr/ cmdline environ io mem ns/ pagemap schedstat stat timers
autogroup comm exe limits mountinfo numa_maps personality sessionid statm uid_map
auxv coredump_filter fd/ loginuid mounts oom_adj projid_map setgroups status wchan
cgroup cpuset fdinfo/ map_files/ mountstats oom_score root/ smaps syscall
clear_refs cwd/ gid_map maps net/ oom_score_adj sched stack task/
综上,内核通过一个个的文件来曝露自己的系统配置信息,这种文件,有些是只读的,有些是可写的,有些是动态变化的,例如进程文件,当应用程序读取某个/proc/文件时,内核就会去注册这个文件,之后再调用一组内核函数来处理,将相应的内核参数拷贝到用户态空间,这样用户读这个文件就可以获取到内核的信息。一个大约的图示如下所示:
sysctl
我们熟悉的sysctl是一个Linux,mansysctl可以看见它的功能和用法。它主要是被拿来更改内核的运行时参数,换句话说,它可以在内核运行过程中,动态更改内核参数。
它本质上还是用到了文件的读写操作,来完成用户态和内核态的通讯。它使用的是/proc的一个子目录/proc/sys。和procfs的区别在于:
procfs主要是输出只读数据,而sysctl输出的大部份信息是可写的。
比如,我们比较常见的是通过cat/proc/sys/net/ipv4/ip_forward来获取内核网路层是否容许转发IP数据包,通过echo1>/proc/sys/net/ipv4/ip_forward或则sysctl-wnet.ipv4.ip_forward=1来设置内核网路层容许转发IP数据包。
同样的操作,Linux也提供了文件/etc/sysctl.conf来让你进行批量更改。
sysfs
sysfs是Linux2.6才引入的一种虚拟文件系统,它的做法也是通过文件/sys来完成用户态和内核的通讯。和procfs不同的是中国linux,sysfs是将一些本来在procfs中的,关于设备和驱动的部份,独立下来,以“设备树”的方式呈现给用户。
sysfs除了可以从内核空间读取设备和驱动程序的信息linux内核空间访问用户空间,也可以对设备和驱动进行配置。
我们看下/sys下有哪些:
# ls /sys
block bus class dev devices firmware fs hypervisor kernel module power
可以见到这种文件基本上都跟计算机的设备和驱动等息息相关的。更多关于那些文件的解释你们可以自行了解linux内核空间访问用户空间,这儿就不过多展开了。
netlink
netlink是Linux用户态与内核态通讯最常用的一种方法。Linuxkernel2.6.14版本才开始支持。它本质上是一种socket,常规socket使用的标准API,在它头上同样适用。诸如创建一个netlinksocket,可以调用如下的socket函数:
#include
#include
#include
netlink_socket = socket(AF_NETLINK, socket_type, netlink_family);
netlink这些灵活的形式,致使它可以用于内核与多种用户进程之间的消息传递系统,例如路由子系统,防火墙(Netfilter),ipsec安全策略等等。
引申:
net-tools工具通过procfs(/proc)和ioctl系统调用去访问和改变内核网路参数配置,而iproute2则通过netlink套接字插口与内核通讯,后者早已被淘汰了,前者逐渐成为标准。
总结
Linux用户态和内核态通讯主要的四种形式,其中netlink和procfs是最常见的形式。
后台回复“加群”,带你步入前辈如云交流群
我的公众号「Linux云估算网路」(id:cloud_dev),号内有10T书籍和视频资源,后台回复「1024」即可申领红旗linux6.0,分享的内容包括但不限于Linux、网络、云估算虚拟化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎你们关注。
参考:
本文原创地址://q13zd.cn/lyhthnhtdtxf.html编辑:刘遄,审核员:暂无