Linux用戶態與內核態通訊的幾種方式

本文首發於個人公衆號 Linux雲計算網絡(id: cloud_dev),專一於乾貨分享,號內有 10T 書籍和視頻資源,後臺回覆「1024」便可領取,歡迎你們關注,二維碼文末能夠掃。html

Linux 用戶態和內核態因爲 CPU 權限的限制,通訊並不像想象中的使用進程間通訊方式那麼簡單,今天這篇文章就來看看 Linux 用戶態和內核態究竟有哪些通訊方式。linux

咱們日常在寫代碼時,通常是在用戶空間,經過系統調用函數來訪問內核空間,這是最經常使用的一種用戶態和內核態通訊的方式。(關於 Linux 用戶態和內核態能夠參考 xx)編程

除此以外,還有如下四種方式:ubuntu

  • procfs(/proc)
  • sysctl(/proc/sys)
  • sysfs(/sys)
  • netlink 套接口

procfs(/proc)

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

咱們熟悉的 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

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

相關文章
相關標籤/搜索