Building header files into the kernel
Fernandes first posted this work in January; version 5 was posted on March 20. As part of the build process, it gathers up all of the kernel's headers (the ".h" files) and a few other artifacts into a compressed tar file; that file is then built into a kernel module. If that module is loaded into the running kernel, the tar file containing the headers can be read from /proc/kheaders.tgz. This is, thus, a way of allowing applications to access the header files that were used to build whatever kernel is running at the moment.
The purpose of this mechanism is to make those header files available in situations where they are otherwise unavailable. In particular, developers building kernel modules need access to this information, as do those who are building BPF programs to analyze a system's behavior. In some systems, notably Android-based devices, those header files are almost certainly not easily available. Fernandes has tried other solutions to this problem, such as BPFd, in the past, but all have fallen short. Providing headers with the kernel itself is the solution he has settled on.
Some of the initial reviews were less than entirely favorable; Christoph
Hellwig described
it as "a pretty horrible idea and waste of kernel memory
"
while Alexey Dobriyan said that it was
"gross
".
H. Peter Anvin also questioned
the memory use and suggested that the data should, at a minimum, be stored
in a swappable filesystem. Numerous others chimed in as well, describing
the work as a "hack" and saying that, rather than building the tar file
into a kernel module, it would be far more straightforward to just place
that file in the module directory where it could be read directly.
At the same time, a number of other developers have indicated that this feature
would be useful; Daniel Colascione even asked
whether it could be expanded to hold all of the kernel source.
Nobody seems to disagree with the overall objective of this work. There are times when the kernel headers are needed for development, but those headers tend to be absent on systems like Android. The disagreement is over the idea of building those headers into the kernel itself. This opposition is easy enough to understand; the kernel itself does not need that information to function, so there would have to be a strong reason indeed to sacrifice that much system memory to hold it in kernel space.
There are indeed reasons for doing so, many of which seem to come down to how Android systems are built rather than something more technical. It would be nice if Android simply had a "kernel headers" package but, as Fernandes explained, that is not really practical:
The seeming aversion to putting anything GPL-licensed into the system image rubs some developers the wrong way, but it is consistent with the GPL avoidance practiced in most of the Android system. There is another reason why putting the kernel headers there is not a complete solution, though: developers will often cross-build a kernel and ship it to a device for direct booting with the fastboot command. Any headers stored on the device itself will not match that new kernel, so they are useless at best. If the headers are built into the kernel itself, though, they will transfer to the device with that kernel and always be correct.
Even for kernels shipped with devices, though, the "store the headers in the filesystem" solution is problematic. As Fernandes noted, the Android project does not have much control over what vendors put onto their devices or where it goes, so it would be difficult (if not impossible) to mandate the presence of the kernel headers in any sort of standard location. Android can, though, mandate that specific kernel configuration options must be set; with this patch merged, vendors could be made to ship the headers for their kernels in a place where they could always be found. Even if vendors tend to hide their kernel modules in strange places (and they are vendors, so of course they do), the user space code on any given device knows how to find and load them.
In other words, building this information into the kernel is, among other
things, a technical solution to the social problem of getting vendors to
provide that information in a consistent way. Sometimes such solutions can
be what is needed. As Colascione put
it: "here's the bottom line: without this work, doing certain
kinds of system tracing is a nightmare, and with this patch, it Just
Works
". Or, as Karim Yaghmour described
it:
Proponents argue that, since the information is built into a kernel module, it can be configured out (or simply not loaded) when it is not needed. Anvin worried, though, that mechanisms like this tend to grow into a mandatory role over time.
One associated question is whether providing kernel header files is the
best way to provide the needed information to user space. Steve Rostedt said
that he would rather have a table describing the kernel's structures,
including the offset, size, and type of each field. That is the information
that is actually needed much of the time, and it could be more compact than
the source code is. Colascione sympathized
with the desire for a cleaner format, but argued that it would be better to
go with what works now: "Think of the headers as encoding this
information and more and the C compiler as a magical decoder ring
".
Header files also include macros, constant definitions, and other
information needed to build BPF programs.
The discussion has gone on at length, provoked anew by each new posting of
the patch set. It does not appear to have changed a lot of minds on either
side of the debate. Sooner or later, presumably as the 5.2 merge window
approaches, somebody (most likely Andrew
Morton) will have to make a decision. Given the evident
advantages from this patch set, it seems likely that Android kernels may
ship it regardless, so it may be mostly a matter of whether the mainline
follows suit.
| Index entries for this article | |
|---|---|
| Kernel | Build system |
| Kernel | Modules |
