这个单体代码库的内容是什么?
我了解处理器架构支持、安全性和虚拟化,但我无法想象超过 600,000 行左右。
内核代码库中包含驱动程序的历史和当前原因是什么?
这 15 多万行是否包括每个硬件的每个驱动程序?如果是这样,那就引出了一个问题,为什么驱动程序嵌入在内核中,而不是从硬件 ID 自动检测和安装的单独软件包?
对于存储受限或内存受限的设备,代码库的大小是否是一个问题?
如果所有这些都被嵌入,它似乎会使空间受限的 ARM 设备的内核大小膨胀。预处理器是否剔除了很多行?说我疯了,但我无法想象一台机器需要那么多逻辑来运行我所理解的内核角色。
是否有证据表明,由于其看似不断增长的性质,规模将在 50 多年后成为问题?
包括驱动程序意味着它会随着硬件的制造而增长。
编辑:对于那些认为这是内核本质的人,经过一些研究,我意识到并非总是如此。内核不需要这么大,因为 Carnegie Mellon 的微内核Mach 被列为“通常不到 10,000 行代码”的例子
小智 86
根据针对 3.13 的cloc run,Linux 大约有 1200 万行代码。
lsmod | wc 在我的 Debian 笔记本电脑上显示 158 个模块在运行时加载,因此动态加载模块是一种很好的支持硬件的方式。
健壮的配置系统(例如make menuconfig)用于选择要编译的代码(更重要的是,不编译哪些代码)。嵌入式系统.config仅使用他们关心的硬件支持来定义自己的文件(包括支持内核内置的硬件或作为可加载模块)。
use*_*552 77
对于任何好奇的人,这里是 GitHub 镜像的行数细分:
=============================================
Item Lines %
=============================================
./usr 845 0.0042
./init 5,739 0.0283
./samples 8,758 0.0432
./ipc 8,926 0.0440
./virt 10,701 0.0527
./block 37,845 0.1865
./security 74,844 0.3688
./crypto 90,327 0.4451
./scripts 91,474 0.4507
./lib 109,466 0.5394
./mm 110,035 0.5422
./firmware 129,084 0.6361
./tools 232,123 1.1438
./kernel 246,369 1.2140
./Documentation 569,944 2.8085
./include 715,349 3.5250
./sound 886,892 4.3703
./net 899,167 4.4307
./fs 1,179,220 5.8107
./arch 3,398,176 16.7449
./drivers 11,488,536 56.6110
=============================================
Run Code Online (Sandbox Code Playgroud)
drivers有助于大量的行数。
Pet*_*des 53
驱动程序在内核中维护,因此当内核更改需要对函数的所有用户进行全局搜索和替换(或搜索和手动修改)时,由进行更改的人完成。由进行 API 更改的人更新您的驱动程序是一个非常好的优势,而不是在更新的内核上无法编译时必须自己完成。
另一种选择(对于树外维护的驱动程序会发生这种情况),补丁必须由其维护人员重新同步以跟上任何更改。
快速搜索引发了关于树内驱动程序开发与树外驱动程序开发的争论。
Linux 的维护方式主要是将所有内容都保存在主线存储库中。配置选项支持构建小型精简内核以控制#ifdefs。因此,您绝对可以构建微小的精简内核,这些内核仅编译整个 repo 中的一小部分代码。
Linux 在嵌入式系统中的广泛使用导致比多年前 Linux 内核源代码树较小时更好地支持遗漏内容。超小 4.0 内核可能比超小 2.4.0 内核小。
Oli*_*Oli 47
到目前为止的答案似乎是“是的,有很多代码”并且没有人用最合乎逻辑的答案来解决这个问题:15M+?所以呢?1500万行源代码和鱼的价格有什么关系?是什么让这如此难以想象?
Linux 显然做了很多。比什么都重要......但是你的一些观点表明你不尊重它构建和使用时发生的事情。
并非所有内容都已编译。内核构建系统允许您快速定义选择源代码集的配置。有些是实验性的,有些是旧的,有些不是每个系统都需要的。看看/boot/config-$(uname -r)(在 Ubuntu 上)中make menuconfig,你会看到有多少被排除在外。
这是一个可变目标桌面发行版。嵌入式系统的配置只会引入它需要的东西。
并非所有内容都是内置的。在我的配置中,大多数内核功能都构建为模块:
grep -c '=m' /boot/config-`uname -r` # 4078
grep -c '=y' /boot/config-`uname -r` # 1944
Run Code Online (Sandbox Code Playgroud)
需要明确的是,这些可全部内置......正如他们可以打印出来,做成一个巨大的纸三明治。除非您为离散硬件工作进行自定义构建(在这种情况下,您已经限制了这些项目的数量),否则这没有意义。
模块是动态加载的。即使系统有数千个模块可用,系统也将允许您只加载您需要的东西。比较以下输出:
find /lib/modules/$(uname -r)/ -iname '*.ko' | wc -l # 4291
lsmod | wc -l # 99
Run Code Online (Sandbox Code Playgroud)
几乎没有加载任何东西。
微内核不是一回事。只需 10 秒钟查看您链接的维基百科页面的主要图像,就会突出显示它们的设计方式完全不同。
Linux 驱动程序是内部化的(主要是动态加载的模块),而不是用户空间,并且文件系统同样是内部的。为什么这比使用外部驱动程序更糟糕?为什么微型更适合通用计算?
评论再次强调你没有得到它。如果您想在离散硬件(例如航空航天、TiVo、平板电脑等)上部署 Linux,您可以将其配置为仅构建您需要的驱动程序。您可以在桌面上使用make localmodconfig. 您最终会得到一个零灵活性的小型专用内核构建。
对于像 Ubuntu 这样的发行版,一个 40MB 的内核包是可以接受的。不,擦洗,它实际上比将 4000 多个浮动模块保留为包的大规模存档和下载方案更可取。它为他们使用更少的磁盘空间,更容易在编译时打包,更容易存储并且对他们的用户(拥有一个可以正常工作的系统)更好。
未来似乎也不是问题。CPU 速度、磁盘密度/定价和带宽改进的速度似乎比内核的增长快得多。10 年后的 200MB 内核包不会是世界末日。
它也不是单向街。如果不维护,代码确实会被踢出。
Ale*_*lex 23
tinyconfig 气泡图svg(小提琴)
从内核构建创建 json 的shell 脚本,与http://bl.ocks.org/mbostock/4063269 一起使用
编辑:原来unifdef有一些限制(-I被忽略和-include不受支持,后者用于包含生成的配置标头)此时使用cat并没有太大变化:
274692 total # (was 274686)
Run Code Online (Sandbox Code Playgroud)
脚本和程序已更新。
除了驱动程序、架构等,还有很多条件代码编译与否取决于选择的配置,代码不一定在动态加载的模块中,而是内置在核心中。
因此,下载了linux-4.1.6 源,选择了tinyconfig,它不启用模块,老实说,我不知道它启用了什么或用户在运行时可以用它做什么,无论如何,配置内核:
# tinyconfig - Configure the tiniest possible kernel
make tinyconfig
Run Code Online (Sandbox Code Playgroud)
构建内核
time make V=1 # (should be fast)
#1049168 ./vmlinux (I'm using x86-32 on other arch the size may be different)
Run Code Online (Sandbox Code Playgroud)
内核构建过程留下*.cmd用命令行调用的隐藏文件,也用于构建.o文件,处理这些文件并提取script.sh下面的目标和依赖项副本,并将其与find一起使用:
find -name "*.cmd" -exec sh script.sh "{}" \;
Run Code Online (Sandbox Code Playgroud)
这为.o名为的目标的每个依赖项创建一个副本.o.c
.c 代码
find -name "*.o.c" | grep -v "/scripts/" | xargs wc -l | sort -n
...
8285 ./kernel/sched/fair.o.c
8381 ./kernel/sched/core.o.c
9083 ./kernel/events/core.o.c
274692 total
Run Code Online (Sandbox Code Playgroud)
.h 标头(已清理)
make headers_install INSTALL_HDR_PATH=/tmp/test-hdr
find /tmp/test-hdr/ -name "*.h" | xargs wc -l
...
1401 /tmp/test-hdr/include/linux/ethtool.h
2195 /tmp/test-hdr/include/linux/videodev2.h
4588 /tmp/test-hdr/include/linux/nl80211.h
112445 total
Run Code Online (Sandbox Code Playgroud)
小智 11
从一开始就在 Tananbaum 和 Torvalds 之间公开辩论单片内核的权衡。如果您不需要为所有事情都进入用户空间,那么内核的接口可以更简单。如果内核是单体的,那么它可以在内部进行更优化(也更凌乱!)。
很长一段时间以来,我们已经将模块作为折衷方案。它正在继续使用 DPDK(将更多网络功能移出内核)之类的东西。添加的内核越多,避免锁定就越重要;所以更多的东西会进入用户空间,内核会缩小。
请注意,单片内核不是唯一的解决方案。在某些架构上,内核/用户空间边界并不比任何其他函数调用更昂贵,这使得微内核具有吸引力。