$Id: README.headers,v 1.8 2002/05/03 21:17:06 srivasta Exp $ This is the Debian GNU/Linux prepackaged version of the Linux kernel headers. Linux was written by Linus Torvalds and others. The kernel sources may be retrieved from ftp.us.kernel.org:/pub/linux/kernel/ This package contains the Linux kernel header files. Kernel Headers and libc6-dev package ____________________________________ ==================================== Need for kernel include files ==== === ====== ======= ===== Even though GNU libc 2.0 (a.k.a. libc6) provides an uniform interface to C programmers, one should realize that it needs different underpinnings on different architectures and operating systems (remember, glibc2 is multi-OS). glibc provides all the standard files that the C standard and POSIX require, and those in turn call in OS and platform specific headers as required transparently to the user. There is an a complete divorce of the kernel-level interface from the user-level interface: the application programmer does not need to know kernel level details at all. But this has been taken by some to mean that /usr/include/{linux,asm} would be superfluous, which is a technical impossibility given that glibc2 is not an architecture and OS specific library. I do not believe it is easy for glibc to present an interface that does not match the underlying OS, and quite possibly people just punted. If there is a mismatch between the user level structures and the kernel level structures, then libc6 library shall have to install translating wrappers around system calls (not such a great idea for high performance systems). I can foresee cases where it would not be possible to implement these wrappers, given a sufficiently large set of architectures and OS's. In the case of Linux, the kernel header files are the underpinnings of the architecture independent interface. Take a simple general ANSI C include file like . This in turn includes /usr/include/errnos.h, which includes /usr/include/linux/errno.h, which in turn includes /usr/include/asm/errno.h. See? A simple, standard include file like , and one needs kernel include files for that. Traditional two symlink approach =========== === ======= ======== Under libc5, it was standard for part of the user interface to libc to be exported from the kernel includes, via /usr/include/linux and /usr/include/asm. Traditionally, this was done by linking those two directories to the appropriate directories in /usr/src/linux/include. This is the method documented in the install instructions for the kernel sources, even today. Why that is bad === ==== == === Kernel headers no longer make sense exporting to user space (in early days of Linux, that was not true). It is beginning to get harder to synchronize the libc and the kernel headers as in the old days; now linking with the latest kernel headers may subtly break new code since the headers linked with are different from the compiled library. In addition, the specter of programs breaking with new kernel headers was preventing needed new features from being added to the kernel (and damping innovative experimentation in kernel development) (see appendix A for details). Besides, the kernel itself no longer needs /usr/include/linux/* at all, so keeping the libc and kernel headers the same aren't needed for kernel development. The headers were included in Debian's libc5-dev after a rash of very buggy alpha kernel releases (1.3.7* or something like that) that proceeded to break compilations, etc. Kernel versions are changed far more rapidly than libc is, and there are higher chances that people install a custom kernel than they install custom libc. Add to that the fact that few programs really need the more volatile elements of the header files (that is, things that really change from kernel version to kernel version), [before you reject this, consider: programs compiled on one kernel version usually work on other kernels]. For the few that do need specific kernel headers, use -I/usr/src/kernel-headers- or some thing for a specific kernel version, or -I/usr/src/linux/include for the latest set of headers installed.. Most programs, even if they include , do not really depend on the version of the kernel, as long as the kernel versions are not too far off, they will work. And the headers provided in libc5-dev (and libc6-dev) are just that. Consider this: Namespace contention between the C library and the kernel (GNU libc is not a Linux only entity) Also, different library versions want different #defines and type defines in different places. Some libraries want to define their own FD_SET, while older ones want to get the kernel ones. This is a mess. Kernel headers can't change anymore, even when the interfaces are not really changing, since one does not know what breaks in userland libraries. The solution is to separate out the two sets of header files: the kernel uses one frequently changing set, and a set of headers is provided from a known good kernel version, which is tested, known to be stable, and that is sufficient for compiling most programs, (it also makes the compile time environments for programs on Debian machines a well known one, easing the process of dealing with problem reports). Debian's libc5 method ======== ===== ====== It was decided, then, to have libc5 development package include files found one specific kernel-sources to insulate most systems from the vagaries of bleeding edge kernel sources, and to prevent subtle breakage introduced by the difference in the headers a program is compiled versus headers the libc was compiled with. As mentioned before, most programs are not coupled tightly enough to kernel data structures, and would continue to work even if the user upgrades the kernel (and presumably the libc development package is not allowed to lag too far behind current kernels). There are two different capabilities which are the issue, and the kernel-packages and libc5-dev address different ones: a) The kernel packages try to provide a stable, well behaved kernel and modules, and may be upgraded whenever there are significant advances in those directions (bug fixes, more/better module support, etc). These, however, may not have include files that are non-broken as far as non-kernel programs are concerned, and the quality of the development/compilation environment is not the kernel packages priority (Also, please note that the kernel packages are tied together, so kernel-source, headers, and image are produced in sync) b) Quality of the development/compilation environment is the priority of libc development package, and it tries to ensure that the headers it provides would be stable and not break non-kernel programs. This assertion may fail for alpha kernels, which may otherwise be perfectly stable, hence the need for a different set of known-good kernel include files. Shortcoming of the libc5 method =========== == === ===== ====== Unfortunately, the proposal for libc5 is beginning to unravel at the edges, since Debian is going truly multi-architecture (and there are murmurs of multi-OS Debian). The reason I say that the solution is unraveling at the edges is that the kernel header files are getting to be quite architecture dependent. We still want to make libc6-dev include headers from a well known stable kernel source. But there is no one set of headers to install, since different architectures need different (sometimes radically different) files. If libc development packages continued to include kernel headers explicitly, we would need different headers for different architectures, resulting in libc6-dev-i386, libc6-dev-m68k, et. al. Or we could maintain all the files in libc6-dev as a set of (quite large) arch dependent patches. But those files are precisely the files contained in kernel-headers-2.0.32. Even in the case of more than one architecture sharing a common kernel-header file set, all I say is that this invariant is not guaranteed for any future releases. Kernel headers need not be the same for any two given architectures. Any solution would do well to address that. However, the following still remains true: the libc development packages should include a static, stable, tested, known good kernel headers to insulate developers from the vagaries of unstable kernel headers (and the subtler pitfall of compiling with headers that do not match the libc being linked with). Debian's old libc6 method ======== === ===== ====== The previous solution was a variant of the original, bad, symlink solution. The variation was that we link to header files from a specific kernel version, namely 2.0.32, which are the headers that libc was compiled with. Whereas we used to link to any old kernel in the original libc5 symlink, the new libc6 symlink was to /usr/src/kernel-header-2.0.32, which holds headers from a *static, well known*, *supported*, tested kernel version, and we let the kernel-headers package handle architecture dependencies (which it had to anyway). One should also consider that the libc maintainer has enough on their plates, and should not be expected to be responsible for the creation and testing of the arch dependent diffs. Coupled with the fact that the afore-mentioned diffs are exactly what is there in kernel-headers package, it exists already, and requires no work on the part of the libc maintainer. So, a dependency was created on kernel headers rather than create kernel header sized architecture dependent diffs. The dependency was such that it libc6-dev linked to the directory /usr/src/kernel-header-2.0.32. At one point libc6-dev pointed to /usr/src/linux-2.0.32, which was a symbolic link. This link was provided by just the packages kernel-source-2.0.32 or kernel-headers-2.0.32, and *no other* kernel package. However, that was pointed out to be an error, since the headers required are architecture dependent, as is kernel-headers-, but kernel-source- is an arch: all (arch independent package), and hence does not provide kernel headers that meet libc6 requirements. So, libc6-dev depends could then provide 2.0.32 kernel headers *for all architectures*, with no messy architecture dependent patches, we always had fixed, static, known good headers in /usr/include/{linux,asm}, and this was goodness. Or was it? This was a working technical solution to having libc development package contain/depend on a well known static set of kernel headers (insulating the vast majority of programs that are not closely tied to kernel version specific internal data structures), while allowing the kernel headers to vary from architecture to architecture, and still allowing device driver authors from having any set of kernel headers they want on the machine through the simple artifice of adding a -I flag to the compilation flags. Indeed, had we thought of the this solution in libc5 days it would have been cleaner (and produced less confusion now). The solution of having libc5-dev depend on kernel-headers-X.XX.XX wold have worked just as well in the libc5 case as it did in the libc6 case. I don't see a change in the situation, just a switch to an equivalent, possibly cleaner, solution. Shortcoming of the old libc6 method =========== == === === ===== ====== Even though the method for libc6 outlined above was a working technical solution, it was confusing to the users, who did not understand why the kernel sources could not be substituited in place, and what happened when the went to a new kernel version. This confusion led us to believe that human factors dictated that a new, less confusing solution had to be implemented. Variations on the old libc6 method ========== == === === ===== ====== The interim solution was an amalgam of the libc5 and the old libc6 solutions. A new package, libc-kheaders, was created, and libc6-dev depended on it. libc-kheaders contained the a well known static set of kernel headers, which were identical to the set of headers used in the libc6 solution outlined above, except that the headers unpacked in /usr/include/{linux,asm}, and no symbolic links were used at all. So, in some respects, we reverted to the libc5 solution of no symlinks in /usr/include, while retaining the flexibility of allowing for the different needs for different architectures. It was my hope that this method would be less confusing. Debian's New libc6 method ======== === ===== ====== Unfortunatly, it turned out that having libc depend on an external package was too confusing for some users. Getting rather weary of answering the questions on the users list, and explaining again why a separation between the kernel and application headers was desirable, the decision was made to ship *ALL* headers, irrspective of architecture, for a particular kernel version in libc6 package itself. So, no external packages. So much for the elegance of the old libc6 method. We are now back to brute force, including all headers for every architecture. Authors response to complaints that Debian is doing it's own thing ======= ======== == ========== ==== ====== == ===== ==== === ===== Yes, Debian is different. It has a package management system. Different part of Debian work with each other. There are assumptions part of the distribution make about itself, and because of this set of co-operating assumptions, or rules, or policy, Debian is better integrated than most Linux distributions I have seen. We often do not do things the "standard" way. Like when we started including /usr/include/{linux,asm} directories instead of having symlinks. It is different. And was acknowledged to be technically superior. Again, we are making changes that shall not be reflected in other distributions. I think we are making the technically superior choice. But we shall be different again. I think this solution works. It is not as elegant as depending on an externel libc-kheaders package, but we can't have everything. ______________________________________________________________________ Appendix A ======== = This document contains comments from Linus Torvalds (made in an ``off-the-cuff'' personal email) to help clarify the rationale behind the Debian way of handling symlinks, but this should not be seen as an official policy statement by Linus. I'm attaching a disclaimer in his own words. The only reason that Linus's message is quoted in here is that he can explain the technical reasons with far more lucidity than I can, and now that I have permission to include his mail, I am removing most of my far less facile efforts in that regard. Need for isolating the C development Library from volatile kernel headers ---------------------------------------------------------------------------- >> "David" == David Engel said on Mon, 24 Feb 1997 >> "Linus" == Linus Torvalds said on Mon, 24 Feb 1997 David> Hi Linus, David> No matter how well we try to explain ourselves, the symlinks issue David> keeps coming up. Would you mind if we used your message below in David> our responses? Linus> Sure. Don't make it "the word of God" - please point out that Linus> it was a off-the-bat personal reply to a question concerning Linus> this, and while I'm more than happy to have the email Linus> circulated it shouldn't be seen as a "official" document in any Linus> way.. Linus> Linus --------------------------------------------------------------------------- >> "Linus" == Linus Torvalds said on Wed, 22 Jan 1997: Linus> The kernel headers used to make sense exporting to user space, Linus> but the user space thing has grown so much that it's really not Linus> practical any more. The problem with Debian is just that they Linus> are different, not that they are doing anything wrong. That Linus> leads to differences between the distributions, and that in Linus> turn obviously can result in subtle problems. Linus> As of glibc, the kernel headers will really be _kernel_ Linus> headers, and user level includes are user level Linus> includes. Matthias Ulrich did that partly because I've asked Linus> him to, but mainly just because it is no longer possible to try Linus> to synchronize the libc and the kernel the way it used to Linus> be. The symlinks have been a bad idea for at least a year now, Linus> and the problem is just how to get rid of them Linus> gracefully. Personally, I'm counting on glibc, which we are Linus> already using on alpha. Linus> Just to give you some idea of exactly why the includes really Linus> can't be handled by simple symlinks: the main problem is Linus> version skew. Lots of people want to upgrade their library Linus> without affecting the kernel, and probably even more people Linus> want to be able to upgrade their kernel without affecting their Linus> compilation environment. Right now doing that has been Linus> extremely fragile. Linus> Just to give _one_ example of why the symlinks are bad: NR_OPEN Linus> and "fd_set". I have had no end of problems making NR_OPEN Linus> larger in the kernel, exactly _because_ of the damn Linus> sym-links. If I just make NR_OPEN larger (the right thing to Linus> do), the problem is that people with old libraries will now Linus> compile against a header file that doesn't match the library Linus> any more. And when the library internally uses another NR_OPEN Linus> than the new program does, "interesting" things happen. Linus> In contrast, with separate header files, this doesn't make any Linus> difference. If I change NR_OPEN in the kernel, the compilation Linus> environment won't notice UNTIL the library and associated Linus> header files are changed: thus the user will continue to compile Linus> with the old values, but because we'll still be binary Linus> compatible, the worst thing that happens is that new programs Linus> won't take advantage of new features unless the developer has Linus> upgraded his library. Compare that to breaking subtly. Linus> NR_OPEN is just _one_ example, and actually it's one of the Linus> easier ones to handle (because the only thing that really makes Linus> much of a difference when it comes to NR_OPEN is the fd_set Linus> size - but it certainly bit some people). Another major problem Linus> is name-space pollution: the POSIX/ANSI/XOpen rules are not Linus> only complex, but they are actually contradictory too. And the Linus> kernel header files really can't reasonably support all of the Linus> intricacies very cleanly. Linus> One specific example of why we want separate header files for Linus> libraries and kernel is offered by glibc: Matthias wanted to Linus> have a "sigset_t" that will suffice for the future when the Linus> POSIX.1b realtime signals are implemented. But at the same time Linus> he obviously wants to be able to support programming on Linus> Linux-2.0 and the current 2.1 that do not have that support. Linus> The _only_ reasonably clean way to handle these kinds of Linus> problems is to have separate header files: user programs see a Linus> larger sigset_t, and then the library interaction with the Linus> kernel doesn't necessarily use all of the bits, for Linus> example. Then later, when the kernel support is actually there, Linus> it's just a matter of getting a new shared library, and voila, Linus> all the realtime signals work. Linus> The symlink approach simply wouldn't work for the above: that Linus> would have required everybody who uses the library to have a Linus> recent enough kernel that whatever magic all the above entails Linus> would be available in the kernel header files. But not only Linus> don't I want to pollute the kernel header files with user level Linus> decisions, it's actually possible that somebody wants to run Linus> glibc on a 1.2.x kernel, for example. We _definitely_ do not Linus> want him to get a 32-bit sigset_t just because he is happy with Linus> an old kernel. Linus> Anyway, this email got longer than intended, but I just wanted Linus> to make clear that the symlinks will eventually be going away Linus> even in non-Debian distributions. Debian just happened to do it Linus> first - probably because Debian seems to be more interested in Linus> technical reasons than any old traditions. And technically, the Linus> symlinks really aren't very good. Linus> The _only_ reason for the symlinks is to immediately give Linus> access to new features in the kernel when those happen. New Linus> ioctl numbers etc etc. That was an overriding concern early on: Linus> the kernel interfaces expanded so rapidly even in "normal" Linus> areas that having the synchronization that symlinks offered was Linus> a good thing. Linus> However, the kernel interfaces aren't really supposed to change Linus> all that quickly any more, and more importantly: the technical Linus> users know how to fix things any way they want, so if they want Linus> a new ioctl number to show up they can actually edit the header Linus> files themselves, for example. But having separation is good Linus> for the non-technical user, because there are less surprises Linus> and package dependencies. Linus> Anyway, something like the patch that David suggested will Linus> certainly go in, although I suspect I'll wait for it to become Linus> "standard" and the glibc first real release to take place.