Насколько маленьким может быть ядро linux?
Некоторое время назад я научился конвертировать виртуальные машины в oracle cloud из ubuntu 20.04 в gentoo. Машины предоставляемые в рамках always free tier весьма маломощны. Это в частности приводит к тому, что перекомпиляция ядра превращается в достаточно длительный процесс. У исходного ядра ubuntu 20.04 в конфиге было 7904 параметра. После того, как я сделал:
make localmodconfig && make localyesconfig
число параметров уменьшилось до 1285. Мне стало интересно попробовать выбросить из ядра все лишнее и посмотреть, что получится.
Я буду компилировать ванильное ядро 5.4.0, потому что именно эта версия используется на моей установке gentoo. Для ускорения процесса я компилирую ядро на своей рабочей машине (i7, 8 cores, 64Gb RAM, tmpfs). Готовое ядро я копирую на машину в oracle cloud. Начинать процесс надо с команды:
В результате у вас появится файл .config для минимального ядра текущей архитектуры. В моем случае в этом файле оказалось 284 непустых строк, не являющихся комментариями.
Давайте скомпилируем его и посмотрим на размер ядра:
$ yes ""|make -j$(nproc) $ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c . -rw-rw-r-- 1 kvt kvt 441872 Jan 31 18:09 arch/x86/boot/bzImage 284 $
Это ядро абсолютно бесполезно. Оно не только не может загрузиться но даже не имеет возможности сообщить о возникших проблемах. Давайте это исправим. Для активации параметров я буду использовать команду:
script/config -e config_parameter_name
Итак, наше ядро будет 64-битным, мы активируем вывод диагностики ядра, включаем поддержку терминала, конфигурируем последовательный порт и консоль на нем:
./scripts/config -e CONFIG_64BIT -e CONFIG_PRINTK -e CONFIG_TTY -e CONFIG_SERIAL_8250 -e CONFIG_SERIAL_8250_CONSOLE
Машина в oracle cloud загрузиться с этим ядром не сможет, вывода на консоль не будет. Как оказалось, надо добавить поддержку EFI и ACPI, являющуюся ее зависимостью. Скрипт ./scripts/config не реализует логику добавления обратных зависимостей т.е. если добавить только CONFIG_EFI, то make выкинет этот параметр из конфига. Также стоит отметить, что включение опций часто включает нижележащие опции. Так в случае с включением CONFIG_ACPI автоматически включается, к примеру, поддержка кнопки включения/выключения.
./scripts/config -e CONFIG_ACPI -e CONFIG_EFI -e CONFIG_EFI_STUB
$ yes ""|make -j$(nproc) $ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c . -rw-rw-r-- 1 kvt kvt 1036960 Jan 31 18:13 arch/x86/boot/bzImage 409 $
Это ядро по прежнему не может завершить процесс загрузки, но по крайней мере способно сообщить об этом:
Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. Kernel Offset: 0x22000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) ---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. ]---
Давайте добавим необходимые параметры:
# virtual guest support and pci ./scripts/config -e CONFIG_PCI -e CONFIG_VIRTIO_PCI -e CONFIG_VIRTIO -e CONFIG_VIRTIO_MENU -e CONFIG_PARAVIRT -e CONFIG_HYPERVISOR_GUEST # disk support ./scripts/config -e CONFIG_BLOCK -e CONFIG_SCSI -e CONFIG_BLK_DEV_SD -e CONFIG_SCSI_VIRTIO # filesystems ./scripts/config -e CONFIG_EXT4_FS -e CONFIG_PROC_FS -e CONFIG_SYSFS -e CONFIG_DEVTMPFS -e CONFIG_DEVTMPFS_MOUNT # executable formats ./scripts/config -e CONFIG_BINFMT_ELF -e CONFIG_BINFMT_SCRIPT # network ./scripts/config -e CONFIG_NET -e CONFIG_VIRTIO_NET -e CONFIG_PACKET -e CONFIG_UNIX -e CONFIG_INET -e CONFIG_NET_CORE -e CONFIG_NETDEVICES -e CONFIG_VIRTIO_NET
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c . -rw-rw-r-- 1 kvt kvt 1950368 Jan 31 18:18 arch/x86/boot/bzImage 616 $
И загружаемся. На этот раз ядро успешно находит корневой диск, но в консоли мы видим ошибки:
The futex facility returned an unexpected error code. . * Call to flock failed: Function not implemented
(none) login: root process 182 (login) attempted a POSIX timer syscall while CONFIG_POSIX_TIMERS is not set Password: setgid: Function not implemented
Тоже не получается, но зато нам недвусмысленно подсказывают какой параметр надо добавить. Добавляем его и остальные необходимые параметры:
./scripts/config -e CONFIG_POSIX_TIMERS -e CONFIG_FUTEX -e CONFIG_FILE_LOCKING -e CONFIG_MULTIUSER
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c . -rw-rw-r-- 1 kvt kvt 1979040 Jan 31 18:25 arch/x86/boot/bzImage 623 $
На этот раз нам удается залогиниться:
instance-20210124-1735 login: root Password: Last login: Mon Feb 1 02:25:10 UTC 2021 from 73.239.106.74 on ssh root@instance-20210124-1735:~#
Ура! Ssh тоже работает. Тем не менее в консоли опять есть ошибки:
* Some local filesystem failed to mount . hwclock: Cannot access the Hardware Clock via any known method. hwclock: Use the --verbose option to see the details of our search for an access method. * Failed to set the system clock
[ 2.910198] udevd[360]: inotify_init failed: Function not implemented
Добавляем поддержку часов реального времени, файловой системы vfat и inotify:
./scripts/config -e CONFIG_RTC_CLASS -e CONFIG_DNOTIFY -e CONFIG_INOTIFY_USER -e CONFIG_VFAT_FS
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c . -rw-rw-r-- 1 kvt kvt 2015904 Jan 31 18:36 arch/x86/boot/bzImage 643 $
Хммм, vfat диск по прежнему не может подмонтироваться:
* Some local filesystem failed to mount
А вот и ответ почему в dmesg заодно с еще одной ошибкой:
[ 3.782884] udevd[527]: error creating signalfd [ 4.107698] FAT-fs (sda15): codepage cp437 not found
./scripts/config -e CONFIG_SIGNALFD -e CONFIG_NLS_CODEPAGE_437 -e CONFIG_NLS_ISO8859_1
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c . -rw-rw-r-- 1 kvt kvt 2015904 Jan 31 18:41 arch/x86/boot/bzImage 646 $
Загружаемся, в консоли ошибок нет, но появилась новая ошибка в dmesg:
[ 2.756136] udevd[360]: error creating epoll fd: Function not implemented
./scripts/config -e CONFIG_EPOLL
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c . -rw-rw-r-- 1 kvt kvt 2020000 Jan 31 19:13 arch/x86/boot/bzImage 647 $
Перезагружаемся и на этот раз не видим новых ошибок!
На моей рабочей машине (i7, 8 cores, 64gb RAM, tmpfs) финальная конфигурация собирается за 1m 16s. В oracle cloud с двумя ядрами и на обычном диске этот же процесс занимает 19m 51s.
Получившееся ядро не является абсолютно минимальным. Так, например, включение поддержки сети добавляет кучу разных сетевых адаптеров. Я не стал заниматься перфекционизмом и вычищать абсолютно все, что не нужно. Кроме того хочу предупредить, что хотя загрузка и быстрое тестирование не выявило проблем с отсутствием дополнительных важных компонент ядра скорее всего таковые существуют. Так что если вдруг вы решите переиспользовать мой конфиг пожалуйста тщательно протестируйте ядро для вашего конкретного случая и при необходимости добавьте нужные параметры ядра.
How big is the linux kernel
But typically both kernel and userspace will access the same memory region the same way, for instance huge pages (transparent or otherwise) will also use huge page mappings when in kernel mode. In regards to kernel vs. userspace, there are several nuances into how page tables are set up (and security features, particularly ones introduced after the latest security issues such as Spectre and Meltdown, try to isolate page table mappings from kernel and userspace.)
How large is the Linux kernel compared to Unix?
Not in just LOC (lines of code), but in storage size, as in bytes, megabytes, gigabytes, etc.
Also, any sources where I can download the original-based Unix OS? Thanks!
It is really unclear, what you are asking.
Yes, you can count LOC in the Linux kernel, but you cannot in any commercial UNIX. Therefore it is not really possible to compare those.
What do you mean with «storage size»? You can download the Linux kernel from kernel.org. You can look at the compressed size, you can unpack it and look at the size of the complete source code, you can build a kernel in many different ways to build a tiny kernel containing only the bare minimum or a huge one containing pretty much every possible feature. — What size are you interested in?
There is not a single UNIX, to compare with. There are free Unices like (Free|Open|Net)BSD, and there are also a bunch of commercial ones. There is really no way for a meaningful answer to your question.
Memory management — On x64, how does the Linux, Basically, if the Linux kernel is compiled with -mcmodel=large, gcc compiles with 64 bits absolute addresses which leaves the kernel with slower memory accesses and such. If the kernel isn’t compiled with -mcmodel=large it can use -mcmodel=kernel which sign extends the 32 bits absolute addresses to 64 …
What is the size of the x86_64 linux kernel page?
I am curious what is the size of the x86_64 linux kernel page. I heard that it is 4KB but some other sources tell it is 2MB.
I am also curious if the user kernel page size can be different from the kernel page size. Can linux use 2MB for the kernel page and 4KB for the user page?
The page size on the x86_64 architecture (same as in i386 or IA-32, which is the 32-bit version of the architecture) is 4KiB.
You will also see references to 2MiB because that’s one of the sizes of «huge pages» in the x86_64 architecture, which also allows for 1GiB huge pages, which are used in Linux in some situations as well. (The 32-bit variant i386 or IA-32 has 4MiB huge pages instead.)
Furthermore, the Linux kernel has a feature called «transparent huge pages,» which is often enabled by default in many modern Linux distributions. Whenever a process allocates larger amounts of memory, the Linux kernel might decide to allocate 2MiB aligned chunks of memory and to set the page tables to give the process huge pages instead. But if the system goes into memory pressure and needs to swap out some memory, it’s still able to break that down into separate pages, so it can swap some of them out and keep the others in memory. (In some circumstances, it is also able to reassemble transparent huge pages from an allocation that included single pages.)
In regards to kernel vs. userspace, there are several nuances into how page tables are set up (and security features, particularly ones introduced after the latest security issues such as Spectre and Meltdown, try to isolate page table mappings from kernel and userspace.) But typically both kernel and userspace will access the same memory region the same way, for instance huge pages (transparent or otherwise) will also use huge page mappings when in kernel mode.
Linux Kernel Tutorial for Beginners, The Linux kernel exists in the kernel space, below the userspace, which is where the user’s applications are executed. The flexibility gives its users a big room to actualize their imaginations. Moreover, the monolithic nature of the kernel is a great advantage as it has a high processing ability than the microkernel. The main …
Allocating more than 4 MB of pinned contiguous memory in the Linux Kernel
For some interaction with a PCI device that is being built, we’d like to create large contiguous pieces of memory that the board can access. As it stands now, the largest piece of memory that I’ve been able to allocate is 4 megabytes in size. I’m wondering if there are any methods to create larger regions.
I do know that I can use the boot option mem= to do this, but for numa reasons, I’d rather not go this route. If, on the other hand, someone knew a way to do this, but distribute it over numa nodes, that would be fine.
As I said initially, I’m limited to 4 Megabytes currently. Allocations are currently done by __alloc_pages , which is limited by MAX_ORDER . MAX_ORDER is a compile-time constant, and I’m also concerned that editing it could have affects elsewhere.
If you can compile your PCI device driver into the kernel (that is, not linked as a module), you could try allocating the memory at boot time. That should let you bypass the upper bounds on dynamic allocations. Refer to Linux Device Drivers, ed. 3 ch. 8 for details.
CMA(Contiguous Memory Allocator) are the best solution for your need IMO. You just need to ship to the newest kernel.
How to read linux kernel, any good tools to read kernel?, Before starting with code , some theory knowledge is important. Professional linux kernel architecture book will be of great help. Lxr is good for browsing code online. VI editor with ctags and Taglist plugin is optimal for browsing kernel source code offline. Share.