本文首發於個人公衆號 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