本文首发于个人公众号 Linux云计算网络(id: cloud_dev),专一于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」便可领取,欢迎你们关注,二维码文末能够扫。html
Linux 用户态和内核态因为 CPU 权限的限制,通讯并不像想象中的使用进程间通讯方式那么简单,今天这篇文章就来看看 Linux 用户态和内核态究竟有哪些通讯方式。linux
咱们日常在写代码时,通常是在用户空间,经过系统调用函数来访问内核空间,这是最经常使用的一种用户态和内核态通讯的方式。(关于 Linux 用户态和内核态能够参考 xx)编程
除此以外,还有如下四种方式:ubuntu
procfs
是 进程文件系统 的缩写,它本质上是一个伪文件系统,为何说是 伪 文件系统呢?由于它不占用外部存储空间,只是占用少许的内存,一般是挂载在 /proc
目录下。安全
咱们在该目录下看到的一个文件,其实是一个内核变量。内核就是经过这个目录,以文件的形式展示本身的内部信息,至关于 /proc
目录为用户态和内核态之间的交互搭建了一个桥梁,用户态读写 /proc
下的文件,就是读写内核相关的配置参数。网络
好比常见的 /proc/cpuinfo
、/proc/meminfo
和 /proc/net
就分别提供了 CPU、内存、网络的相关参数。除此以外,还有不少的参数,以下所示:session
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),每一个文件包含该进程全部的配置信息,包括进程状态、文件描述符、内存映射等等,咱们能够看下:dom
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/
文件时,内核才会去注册这个文件,而后再调用一组内核函数来处理,将相应的内核参数拷贝到用户态空间,这样用户读这个文件就能够获取到内核的信息。一个大概的图示以下所示:socket
咱们熟悉的 sysctl 是一个 Linux 命令,man sysctl
能够看到它的功能和用法。它主要是被用来修改内核的运行时参数,换句话说,它能够在内核运行过程当中,动态修改内核参数。函数
它本质上仍是用到了文件的读写操做,来完成用户态和内核态的通讯。它使用的是 /proc
的一个子目录 /proc/sys
。和 procfs 的区别在于:
procfs 主要是输出只读数据,而 sysctl 输出的大部分信息是可写的。
例如,咱们比较常见的是经过 cat /proc/sys/net/ipv4/ip_forward
来获取内核网络层是否容许转发 IP 数据包,经过 echo 1 > /proc/sys/net/ipv4/ip_forward
或者 sysctl -w net.ipv4.ip_forward=1
来设置内核网络层容许转发 IP 数据包。
一样的操做,Linux 也提供了文件 /etc/sysctl.conf
来让你进行批量修改。
sysfs 是 Linux 2.6 才引入的一种虚拟文件系统,它的作法也是经过文件 /sys
来完成用户态和内核的通讯。和 procfs 不一样的是,sysfs 是将一些本来在 procfs 中的,关于设备和驱动的部分,独立出来,以 “设备树” 的形式呈现给用户。
sysfs 不只能够从内核空间读取设备和驱动程序的信息,也能够对设备和驱动进行配置。
咱们看下 /sys
下有什么:
# ls /sys block bus class dev devices firmware fs hypervisor kernel module power
能够看到这些文件基本上都跟计算机的设备和驱动等息息相关的。更多关于这些文件的解释你们能够自行了解,这里就不过多展开了。
netlink 是 Linux 用户态与内核态通讯最经常使用的一种方式。Linux kernel 2.6.14 版本才开始支持。它本质上是一种 socket,常规 socket 使用的标准 API,在它身上一样适用。好比建立一个 netlink socket,能够调用以下的 socket 函数:
#include <asm/types.h> #include <sys/socket.h> #include <linux/netlink.h> 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」 便可领取,分享的内容包括但不限于 Linux、网络、云计算虚拟化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎你们关注。
参考:
https://www.ibm.com/developerworks/cn/linux/l-kerns-usrs/index.html
https://fasionchan.com/blog/2017/06/16/procfs-wei-wen-jian-xi-tong-yuan-li/
https://zh.wikipedia.org/wiki/Netlink