- Насколько маленьким может быть ядро linux?
- How do you get the size of a file in the linux kernel?
- 3 Answers 3
- Kernel Size Tuning Guide
- Contents
- Introduction
- Measuring the kernel
- Measuring the kernel image size
- Measuring the kernel text, data and bss segments
- Measuring and comparing sub-parts of the kernel
- Kernel Size Tuning features
- Linux-tiny patches
- How to configure the kernel
- Kernel Configuration Options
- Special Instructions for some kernel options
- Booting without SysFS
- Booting without /proc fs
- Using kernel memory measurement features
- Outline
- References
- Appendices
- Appendix A — Sample minimum configuration for ARM
- Appendix B — Configuration Option Details
Насколько маленьким может быть ядро linux?
Некоторое время назад я научился конвертировать виртуальные машины в oracle cloud из ubuntu 20.04 в gentoo. Машины предоставляемые в рамках always free tier весьма маломощны. Это в частности приводит к тому, что перекомпиляция ядра превращается в достаточно длительный процесс. У исходного ядра ubuntu 20.04 в конфиге было 7904 параметра. После того, как я сделал:
число параметров уменьшилось до 1285. Мне стало интересно попробовать выбросить из ядра все лишнее и посмотреть, что получится.
Я буду компилировать ванильное ядро 5.4.0, потому что именно эта версия используется на моей установке gentoo. Для ускорения процесса я компилирую ядро на своей рабочей машине (i7, 8 cores, 64Gb RAM, tmpfs). Готовое ядро я копирую на машину в oracle cloud. Начинать процесс надо с команды:
В результате у вас появится файл .config для минимального ядра текущей архитектуры. В моем случае в этом файле оказалось 284 непустых строк, не являющихся комментариями.
Давайте скомпилируем его и посмотрим на размер ядра:
Это ядро абсолютно бесполезно. Оно не только не может загрузиться но даже не имеет возможности сообщить о возникших проблемах. Давайте это исправим. Для активации параметров я буду использовать команду:
Итак, наше ядро будет 64-битным, мы активируем вывод диагностики ядра, включаем поддержку терминала, конфигурируем последовательный порт и консоль на нем:
Машина в oracle cloud загрузиться с этим ядром не сможет, вывода на консоль не будет. Как оказалось, надо добавить поддержку EFI и ACPI, являющуюся ее зависимостью. Скрипт ./scripts/config не реализует логику добавления обратных зависимостей т.е. если добавить только CONFIG_EFI, то make выкинет этот параметр из конфига. Также стоит отметить, что включение опций часто включает нижележащие опции. Так в случае с включением CONFIG_ACPI автоматически включается, к примеру, поддержка кнопки включения/выключения.
Это ядро по прежнему не может завершить процесс загрузки, но по крайней мере способно сообщить об этом:
Давайте добавим необходимые параметры:
И загружаемся. На этот раз ядро успешно находит корневой диск, но в консоли мы видим ошибки:
Тоже не получается, но зато нам недвусмысленно подсказывают какой параметр надо добавить. Добавляем его и остальные необходимые параметры:
На этот раз нам удается залогиниться:
Ура! Ssh тоже работает. Тем не менее в консоли опять есть ошибки:
А в dmesg находим еще:
Добавляем поддержку часов реального времени, файловой системы vfat и inotify:
Хммм, vfat диск по прежнему не может подмонтироваться:
А вот и ответ почему в dmesg заодно с еще одной ошибкой:
Загружаемся, в консоли ошибок нет, но появилась новая ошибка в dmesg:
Перезагружаемся и на этот раз не видим новых ошибок!
На моей рабочей машине (i7, 8 cores, 64gb RAM, tmpfs) финальная конфигурация собирается за 1m 16s. В oracle cloud с двумя ядрами и на обычном диске этот же процесс занимает 19m 51s.
Получившееся ядро не является абсолютно минимальным. Так, например, включение поддержки сети добавляет кучу разных сетевых адаптеров. Я не стал заниматься перфекционизмом и вычищать абсолютно все, что не нужно. Кроме того хочу предупредить, что хотя загрузка и быстрое тестирование не выявило проблем с отсутствием дополнительных важных компонент ядра скорее всего таковые существуют. Так что если вдруг вы решите переиспользовать мой конфиг пожалуйста тщательно протестируйте ядро для вашего конкретного случая и при необходимости добавьте нужные параметры ядра.
Источник
How do you get the size of a file in the linux kernel?
I found this link (http://www.spinics.net/lists/newbies/msg41016.html) and have been looking into doing just that. So I wrote code in a kernel module:
Which will not compile because:
So I am really confused since I was looking at this documentation: http://lxr.free-electrons.com/source/fs/stat.c#L40
And now I see inside /linux/fs.h that the prototype for vfs_getattr is:
Can anyone help me with my implementation? I am reading into vfsmount and dentry but am still lost.
3 Answers 3
The call to this function changes depending on which kernel version you are using. The two argument version was introduced somewhere between 3.8 and 3.9. So if you are using kernel 3.8 or before, you need the «three arguments», and 3.9 onwards, you need two arguments.
If you really want to do this in kernel mode, on an older kernel than 3.9, you may be better off using the vfs_fstat or vfs_stat
However, dealing with files inside the kernel is frowned upon, and you may want to consider if there isn’t a BETTER alternative — for example, if you want to load some file-stuff into the memory of a board that is on your system, you could load the file in a user-mode process, and then pass the loaded parts into the kernel via some private IOCTL type function. This is much more «kernel friendly», and if you are planning on ever trying to get your driver/module included in the overall kernel source code, you probably NEED to do this.
Источник
Kernel Size Tuning Guide
This document describes how to configure the Linux kernel to use a small amount of memory and flash.
Note: This document is a work in progress. Please feel free to add material anywhere you have additional information or data. Sections of this document which need additional work are denoted with [FIXTHIS] markers.
Contents
Introduction
One big problem area when using Linux in an embedded project is the size of the Linux kernel.
Measuring the kernel
There are 3 aspects of kernel size which are important:
- the size of the kernel image stored in flash (or other persistent storage)
- the static size of kernel image in RAM (usually, this will be the size of the uncompressed image)
- This includes the text, data, and BSS segments of the kernel at the time it is loaded. The text and BSS segments will stay the same size for the kernel throughout it execution. However, the data and stack segments may grow according to the needs of the system.
- the amount of dynamic RAM used by the kernel.
- This will fluctuate during system execution. However, there is a baseline amount of memory which is allocated at system startup. Application-specific RAM can be calculated to be above this minimal amount of required RAM.
For now, this document ignores Execute-In-Place (XIP) and Data-Read-In-Place (DRIP) techniques, the use of which have an impact on the amount of flash and RAM used by the kernel. See the following online resources for more information about these techniques: Kernel XIP and Data Read In Place
Measuring the kernel image size
The compressed kernel image is what is stored in the flash or ROM of the target device. The size of this image can be obtained by examining the size of the image file in the host filesystem with the ‘ls -l‘ command:
- for example: ‘ls -l vmlinuz‘ or ‘ls -l bzImage‘ (or whatever the compressed image name is for your platform.)
Measuring the kernel text, data and bss segments
Use the size command to determine the size of the text, data, and BSS segments of a kernel image.
Note that the BSS segment is not stored in the kernel image because it can be synthesized at boot time by filling a block of memory with zeros. Note also that portions of the kernel text and data are set aside in special initialization segments, which are discarded when the kernel finishes booting. Because of these factors, the size command does not give you an exactly correct value for the static kernel RAM size. However, it can be used as a reasonable estimate.
To use the size command, run it with the filename of the uncompressed kernel image (which is usually vmlinux).
Measuring and comparing sub-parts of the kernel
In order to find areas where the kernel size can be reduced, it is often useful to break down the static size of the kernel by sub-system or by kernel symbol. The following sections describe how to see the size of each kernel sub-system, how to see the size of individual kernel symbols, and how to compare the size of symbols between two kernel versions. This is useful because as you make changes to the kernel configuration you can determine what part of the kernel is affected by the change. From this information you may be able to predict what the affect of the change will be, and decide whether the change is acceptable.
Measuring major kernel subsystems
The major sub-systems of the kernel are put into library object files named built-in.o in the corresponding sub-directory for that sub-system within the kernel build directory. The major sub-directories, at the time of this writing (for kernel 2.6.17) are: init, user, kernel, mm, fs, ipc, security, crypto, block, ltt, drivers, sound, net, lib
To see the size of the major kernel sections (code, data, and BSS), use the size command, with a wildcard for the first level of sub-directory:
You can pipe this output through sort to sort by the largest libraries:
To see even greater detail, you can examine the size of built-in.o files even deeper in the kernel build hierarchy, using the find command:
- find . -name "built-in.o" | xargs size | sort -n -r -k 4
Measuring individual kernel symbols
You can measure the size of individual kernel symbols using the ‘nm’ command. Using the nm --size -r vmlinux
Legend: The columns of this output are:
- size in bytes (in hexadecimal)
- symbol type
- symbol name.
The symbol type is usually one of:
- ‘b’ or ‘B’ for a symbol in the BSS segment (uninitialized data),
- ‘t’ or ‘T’ for a symbol in the text segment (code), or
- ‘d’ or ‘D’ for a symbol in the data segment.
Use ‘man nm‘ for additional information on the ‘nm‘ command.
Comparing kernel symbols between two kernel images
Use the bloat-o-meter command, found in the kernel source scripts directory, to compare the symbol sizes between two kernel images.
- /scripts/bloat-o-meter vmlinux.default vmlinux.altconfig
If you get an error: ‘chmod a+x /scripts/bloat-o-meter’
Example output, comparing a baseline kernel to one configured with CONFIG_PRINTK=n:
Kernel Size Tuning features
The Linux kernel includes a number of options for to control the features and options it supports. The kernel, over time, has accumulated a large set of features and capabilities. But many features are not needed in Consumer Electronics products. By carefully tuning the kernel options, you can omit many parts of the kernel and save memory in your product.
Linux-tiny patches
The Linux-tiny patch set is a set of patches maintained by Matt Mackall developed with the intent to help a developer reduce the size of the Linux kernel.
These patches are described at: Linux Tiny
The Linux-tiny patch set includes a number of different patches to allow the kernel to be reduced in size. Sometimes, the size reductions are accomplished by reducing the number of objects for a particular features (like the number of possible swap areas, or the number of tty discipline structures). Sometimes, the size reductions are achieved by removing features or functions from the kernel.
Here is a list of the individual Linux-tiny patches that are available for the 2.6.22 kernel at Linux Tiny Patch Details
Please note that the last patch in this list («do-printk») is available separately from the main Linux-tiny patch set. Please find this patch at: Do Printk
The patches listed in this table represent patches that can be applied to a 2.6.16 Linux kernel. However, as of version 2.6.16, many options for reducing the kernel were already available in Linux. A list of options, both from these patches and from existing code, which are interesting for tuning the kernel size is provided in the section: «Kernel configuration Options»
How to configure the kernel
[FIXTHIS — need detailed kernel configuration instructions]
- use ‘make menuconfig’
- perform thorough testing of your library and applications with the smaller config
- development vs. deployment configurations
- describe all_no config — most times it won’t boot.
Kernel Configuration Options
Here is a table of kernel configuration options, including a description, the default value for a kernel, and the recommended value for a smaller configuration of the kernel:
CONFIG option | Description | Default | Small |
---|---|---|---|
CONFIG_CORE_SMALL | tune some kernel data sizes | N | Y |
CONFIG_NET_SMALL | tune some net-related data sizes | N | Y |
CONFIG_KMALLOC_ACCOUNTING | turn on kmalloc accounting | N | Y * |
CONFIG_AUDIT_BOOTMEM | print out all bootmem allocations | N | Y * |
CONFIG_DEPRECATE_INLINES | cause compiler to emit info about inlines | N | Y * |
CONFIG_PRINTK | allow disable of printk code and message data | Y | N |
CONFIG_BUG | allow elimination of BUG (and BUG_ON??) code | Y | N |
CONFIG_ELF_CORE | allow disabling of ELF core dumps | Y | N |
CONFIG_PROC_KCORE | allow disabling of /proc/kcore | Y | N |
CONFIG_AIO | allow disabling of async IO syscalls | Y | N |
CONFIG_XATTR | allow disabling of xattr syscalls | Y | N |
CONFIG_FILE_LOCKING | allow disabling of file locking syscalls | Y | N |
CONFIG_DIRECTIO | allow disabling of direct IO support | Y | N |
CONFIG_MAX_SWAPFILES_SHIFT | number of swapfiles | 5 | 0 |
CONFIG_NR_LDISCS | number of tty line disciplines | 16 | 2 |
CONFIG_MAX_USER_RT_PRIO | number of RT priority levels (schedule slots) | 100 | 5 |
Other config options | These are not in Linux-tiny, but help with size | default | small |
CONFIG_KALLSYMS | load all symbols for debugging/kksymoops | Y | N |
CONFIG_SHMEM | allow disabling of shmem filesystem | Y | N + |
CONFIG_SWAP | allow disabling of support for a swap segment (virtual memory) | Y | N |
CONFIG_SYSV_IPC | allow disabling of support for System V IPC | Y | N + |
CONFIG_POSIX_MQUEUE | allow disabling of POSIX message queue support | Y | N + |
CONFIG_SYSCTL | allow disabling of sysctl support | Y | N + |
CONFIG_LOG_BUF_SHIFT | control size of kernel printk buffer | 14 | 11 |
CONFIG_UID16 | allow support for 16-bit uids | Y | ?? |
CONFIG_CC_OPTIMIZE_FOR_SIZE | Use gcc -os to optimize for size | Y | Y |
CONFIG_MODULES | allow support for kernel loadable modules | Y | N + |
CONFIG_KMOD | allow support for automatic kernel module loading | Y | N |
CONFIG_PCI | allow support for PCI bus and devices | Y | Y — |
CONFIG_XIP_KERNEL | allow support for kernel Execute-in-Place | N | N |
CONFIG_MAX_RESERVE_AREA | ?? | ?? | ?? |
CONFIG_BLK_DEV_LOOP | support for loopback block device | Y | Y — |
CONFIG_BLK_DEV_RAM | support for block devices for RAM filesystems | Y | Y — |
CONFIG_BLK_DEV_RAM_COUNT | Number of block devices for RAM filesystems | 16 | 2? |
CONFIG_BLK_DEV_RAM_SIZE | Size of block device struct for RAM filesystems | 4096 | ?? |
CONFIG_IOSCHED_AS | Include Anticipatory IO scheduler | Y | Y |
CONFIG_IOSCHED_DEADLINE | Include Deadline IO scheduler | Y | N + |
CONFIG_IOSCHED_CFQ | Include CFQ IO scheduler | Y | N + |
CONFIG_IP_PNP | support for IP autoconfiguration | Y | N + |
CONFIG_IP_PNP_DHCP | support for IP autoconfiguration via DHCP | Y | N + |
CONFIG_IDE | support for IDE devices | Y | N + |
CONFIG_SCSI | support for SCSI devices | Y | N + |
- «Y *» — Set to ‘Y’ for measurement during development, and set to ‘N’ for deployment.
- «N +» — Whether you can set this to ‘N’ depends on whether this feaure is needed by your applications.
- «Y -» — You probably need this, but it might we worth checking to see if you don’t.
Special Instructions for some kernel options
How to use CONFIG_PRINTK
If the «do-printk» patch is applied, there are two options which control the compilation of printk elements in the kernel: CONFIG_PRINTK_FUNC and CONFIG_PRINTK. You can use these options to control how much printk support the kernel provides, and to control on a global basis whether any printk messages at all are compiled into the kernel. Another special preprocessor variable is also available, called DO_PRINTK, which provides the ability to enable printk messages inside a single C compilation unit, even if printk messages are disabled globally.
This section explains how to use these features to reduce the kernel size, while still enabling sufficient printk messages to be useful during development and deployment.
The CONFIG_PRINTK option disables all of the kernel printk calls. By setting this option to ‘N’ in your kernel configuration, all uses of «printk» throughout the kernel source are turned into empty statements, and omitted when the program is compiled. This provides a substantial size savings, since the kernel messages often account for more than 100 kilobytes of space in the kernel image. Setting this option to ‘N’ will not, however, remove the actual
code itself (just the calls to
). The CONFIG_PRINTK_FUNC option controls whether the
function and various helper functions are compiled into the Linux kernel. When this is set to ‘N’, CONFIG_PRINTK is automatically set to ‘N’, and no printk messages are compiled into the kernel. This usually saves about another 4K of size in the kernel image.
By using both CONFIG_PRINTK and CONFIG_PRINTK_FUNC, you can reduce the size of the kernel image (and that flash and RAM it requires). However, there is a drawback to eliminating all the messages. Obviously, it is then not possible to get any status, diagnostic or debug messages from the kernel! Another mechanism is available, which allows you to control on a per-file basis which printk calls are compiled into the kernel. This is the pre-processor variable DO_PRINTK.
To use DO_PRINTK, set CONFIG_PRINTK to ‘N’ and CONFIG_PRINTK_FUNC to ‘Y’ in your kernel configuration. This will globally disable all printk calls in the kernel. Now, determine the C files where you wish to enable printk messages, and add the line:
at the top of each file. Now, the printk calls in those files will be compiled normally. Printk calls in other modules will be omitted.
— Important Note: The DO_PRINTK variable controls how the preprocessor will treat printk statements in the code. For this reason, this statement MUST appear at the top of the file, before any
lines. In order to change the set of printk messages preserved in the code, you will need to modify the
lines, and recompile the kernel. (There is no runtime control of the printk calls.) This is a simple mechanism, but it does provide a way to omit most of the printk messages from the kernel while still preserving some messages that may be useful during
development or on a deployed product.
In review, there are basically 3 different settings combinations for CONFIG_PRINTK_FUNC and CONFIG_PRINTK that make sense:
Settings | Explanation | |
---|---|---|
CONFIG_PRINTK_FUNC | CONFIG_PRINTK | |
Y | Y | This is the default setting for the kernel configuration. In this setting the printk code is compiled into the kernel, and all printk calls throughout the entire source code are also compiled as part of the kernel. |
Y | N | This leaves the actual printk() routine in the kernel, but disables all calls to printk throughout the entire source code. However, you can use DO_PRINTK in individual modules to enable the printk calls from those modules. |
N | N | This removes the printk() routine from the kernel, and disables all kernel printk messages, and gives the smallest kernel code and data size. DO_PRINTK will NOT enable any module-specific printk calls. |
Booting without SysFS
(copied from linux-tiny wiki)
Turning off sysfs support can save a substantial amount of memory in some setups. One big downside is that it breaks the normal boot process because the kernel can no longer mapa symbolic device name to the internal device numbers.
Thus, you will need to pass a numeric device number in hex. For example, to boot off /dev/hda1, which has major number 3 and minor 1, you’ll need to append a root== option like this:
Booting without /proc fs
It is also possible to boot with
fs, but many programs expect this psuedo-filesystem to be present and mounted. For example,
are two commands which retrieve information from
in order to run.
list some workarounds here
Using kernel memory measurement features
FIXTHIS — need instruction on bootmem auditing and counting inlines — need more detail for kmalloc accounting
Kmalloc Accounting
This is a features of Linux-tiny, which tracks callers of kmalloc and kfree, and produces summary statistics for kernel memory allocations, as well as detailed information about specific kmalloc callers.
This was first published by Matt Mackall in February of 2005, but was not mainlined at that time.
To see results for kernel allocations, follow these steps:
- turn on the CONFIG_KMALLOC option. This will show up on the kernel configuration menus as «Enabled accounting of kmalloc/kfree allocations?»
- recompile your kernel
- boot the kernel
- periodically, examine the accounting stats
- cat /proc/kmalloc
Bootmem Auditing
Counting Inlines
Outline
FIXTHIS — need to review outline and fill in missing material
- Tuning the kernel
- how to measure kernel size
- in-kernel size reporting — kmalloc accounting
- bloat-o-meter
- kernel configuration options
- mainline options
- optional features
- minimal config
- sufficient API?
- POSIX compliance
- LSB compliance
- LTP compliance
- file systems
- comparison of file system sizes
- compiler options for reducing size
- gcc -os
- gcc -whole-program
- online resources:
- bloatwatch
- kconfigsize
References
- eLinux wiki Linux-tiny page: Linux Tiny
- Matt Mackall’s https://elinux.org/images//8/83/Pdf.gifLinux-tiny presentationhttps://elinux.org/images/d/da/Info_circle.png
- CE Linux Forum resources for reducing system size: System Size
Appendices
Appendix A — Sample minimum configuration for ARM
[FIXTHIS — need ARM minimum config.]
Appendix B — Configuration Option Details
Want to fill in this section with details about configuration options.
For each option, would like to document:
- what is size affect for different option values
- This page & Kernel Size Tuning Guide Config Option Impact describe kernel size and RAM usage impact affected by each configuration option listed in «Kernel Configuration Options» above, on i386.
- what is affect of performance, functionality, etc.
- what programs (if any) will stop working if option is turned off (or reduced)
Источник