23

Since the majority of the Linux kernel is written in the C language, so when the kernel gets loaded in Main memory, does the standard C library also get loaded along the Linux kernel?

If that's the reason the programs written in C consume less memory than other program as the standard C library is already loaded and as a result are faster also (less page faults) compared to program written in other languages when run on a Linux machine?

3
  • 4
    Regarding memory in "other programs". That is deeply subjective because it's hard to find side by side implementations of the same thing in different languages. However nuances of some other languages make them prone to memory bloat much more than others. 1) "objects" in some other languages come with much more meta data. 2) some languages cannot allocate "objects" on the stack causing bloat to heap space which combined with... 3) lazy garbage collection leaves a lot of heap memory allocated longer than necessary. Java does all three and consequently has memory hungry apps . May 31, 2020 at 22:05
  • Depends on the language, but I would think that many - especially if they're part of gcc - gcc.gnu.org/onlinedocs/gcc/G_002b_002b-and-GCC.html - would just be using the standard C library for a lot of things. Why duplicate the effort of writing code to e.g. efficiently read & write files?
    – jamesqf
    Jun 1, 2020 at 3:50
  • most languages have some sort of runtime metadata and heap allocation. C is almost unique in having none of the former and not even first-class support for the latter
    – Eevee
    Jun 2, 2020 at 9:53

6 Answers 6

45

The kernel is written in C, but it doesn’t use the C library (as dave_thompson_085 points out, it’s “freestanding”). Even if it did, a C library loaded along with the kernel for the kernel’s use would only be available to the kernel (unless the kernel made it explicitly accessible to user space, in some way or other), so it wouldn’t help reduce the memory requirements for programs.

That said, in most cases, the earliest programs run after the kernel starts (programs in the initramfs, although they’ll use their own copy of the C library; and ultimately, init), use the C library, so it ends up being mapped early on, and it’s highly likely that the portions of the library that are widely used will always remain in physical memory.

The kernel contains implementations of many of the C library’s functions, or variants (for example, printk instead of printf); but they don’t all follow the standard exactly. In some circumstances, the implementations of C library functions in the compiler are used instead.

(Note that the vast majority of programs written in languages other than C ultimately use the C library.)

3
  • 2
    In fact, I'd say most other languages rely on a C standard library at some point, often as a dependency of their very own runtime library.
    – jpaugh
    Jun 2, 2020 at 18:38
  • 2
    @jpaugh On Unixes, it's either use the C standard library or reimplement a huge collection of system-specific stuff, as well it being harder to interface with C the less you wrap. On non-C/C++ based systems, it'd be different, but OpenVMS seems to be the only survivor there, to the extent it survives.
    – prosfilaes
    Jun 2, 2020 at 22:09
  • David Kariuki: You say that you’re doing ‘‘Grammar, Punctuation ad Spelling Correction.’’ Can you identify any of your changes that qualify under any of those categories? OK, your suggested edit changes punctuation, but it wasn’t wrong. And you made two spelling errors! Jun 6, 2020 at 4:24
21

Is the standard C library loaded by default in main memory in Linux?

No.

The first userspace process the kernel ever starts is called init, and its purpose is to start everything else, and to reap zombie children (processes whose parent processes exited before they did, so there is no other process to reap their exit status).

Because init almost always uses the standard C library, the standard C library is loaded in memory as soon as init starts. But that's just a side effect, and nothing the kernel cares about.

The kernel has nothing to do with the standard C library. (The kernel is written in freestanding C, an environment where the standard C library is not available.)

2
  • 4
    In the past init used to be statically linked, but with the more feature rich variants (including systemd) it's correct to assume it links against libc.so.
    – eckes
    Jun 1, 2020 at 11:57
  • @eckes actually, even sysvinit 2.86 is linked to libc.so.6 on my system. So I assume it's long since inits started being dynamically-linked
    – Ruslan
    Jun 2, 2020 at 17:41
7

"C standard library" in the kernel's context is more of an abstract form, meaning there is some reusable utility subroutine that does things as specified by the C language. Just like the reusable subroutines that is not defined by the C language but by kernel itself, these do not exist in a "shared object" (dynamic library) form. Instead, they are compiled together with the kernel and assemble into one kernel executable.

You can find some of the library code here, e.g. memcpy, strcmp/strncmp https://elixir.bootlin.com/linux/latest/source/arch/x86/lib

So kernel ships with its own C library implementation and doesn't share it with any other userland code, not does it use a C library that is provided by the user to boot. In fact, each userland program may do the same, e.g. static links (includes, packs) a C library and not share with anyone else.

To answer your last question, no userland program shares C standard library with the kernel.

6

No, the kernel doesn't use the standard C library.

Note that the standard C library (usually glibc is the one used with Linux) is "translating" C calls to kernel syscalls. Lots of things are completely done in userland, but it is built upon the kernel. So it wouldn't be that easy to use a C library that, in binary form, could be used both on the kernel as in userland. Also, the objective of their libraries are usually quite different.

And now, the second part. Each program loads the C library itself, even if pretty much every Linux program in the system is linking to the same standard C library.

You can call grep libc /proc/self/smaps a few times and see how libc is mapped on a different address each time (as a result of ASLR). This is in contrast to Windows, where a few libraries like kernel32.dll (the KnownDLL) are mapped on every process, at the same location, even if not explicitly loaded.

On Linux, the program (well, ld) will need to take the steps for loading libc just like every other dynamic library. Although it's true that the libc is one of the most optimized pieces of code, so that both its loading and general running is quick. Often, at a very low-level (have a look at Ulrich Drepper articles) that wouldn't be worth for normal programs.

If that's the reason the programs written in C consume less memory than other program

So no. The memory space will not consume less memory. The libc will still show the memory usage for the libc on the process.

as the standard C library is already loaded and as a result are faster also (less page faults)

It's true however that the code will already be loaded in memory, so it won't need to fetch it from disk (it is done per page, but the section of code your program needs was probably requested by a different one before).

In fact, Linux will aggressively cache the files in memory. If you have enough memory, once you load a program from disk, it will be cached in memory and it won't load again that code from the (slow) disk. Thus, you could achieve the same effect by loading them from disk in advance / having loaded them before.

compared to program written in other languages when run on a Linux machine?

It's unlikely that you might find them faster due to this small difference. More likely, I would think on the following reasons:

  • Well-written C code being more efficient
  • It is more low-level, this also reflects on how is C programming
  • Compilers able to generate more efficient code
  • libc is very highly optimized Actually, some functions are implemented in assembler.
  • Most other languages are actually built upon libc, not calling the kernel themselves

It's also possible that the other languages are not really that slower. You would need to specify a pair of such programs, in order to compare them equally, and then determine if really the C version if faster, and where the difference actually lies.

3
  • 2
    The C library is highly optimised, but the most aggressively optimised implementations are in the compiler itself nowadays — it can use its built-ins, combined with knowledge of the call sites, to produce faster and/or more compact code than the C library can. Jun 1, 2020 at 20:38
  • I would say that the C library is nowadays tweaked to make use of all those optimizations (whereas in the past, optimizations would make more use of assembler).
    – Ángel
    Jun 4, 2020 at 8:30
  • Compare builds of char * msg = "Hello world\n"; char buf[16]; strncpy(buf, msg, strlen(msg) + 1); printf("%s", buf); with and without optimisation to see what I mean. No C library optimisation can reduce that to movabsq $8031924123371070792, %rax followed by a printf call. That’s an artificial example, but similar patterns are common in real-world code, and they really are optimised like that (or using vector registers), by the C compiler. Jun 4, 2020 at 8:49
4

The short name for the C standard library is libc.

Let's first make clear that libc is a library like any other.

The kernel itself does not use libc (as you can read here).

libc can be linked either dynamically or statically.

Dynamic linking:

The libraryis not embedded into the executable. When the program launches, the library is loaded from a system path. For example /lib/x86_64-linux-gnu/libc.so on linux.

And here it comes: If a second program launches libc is not loaded again. Instead it shares the library with the first program. This means no new memory is needed.

Static linking:

If libc was linked statically then the library is inside the executable. So if you run two programs libc is in memory twice.

7
  • Note that in practice, the memory footprint of static linking is not as disastrous as it sounds. When an executable is linked statically to libc (or any other library), the linker will only include those library routines that are actually used by the executable (so typically just a tiny fraction of the whole libc). They will still be duplicated in memory, but it won't be twice the whole tens-of-megabytes libc.
    – TooTea
    Jun 2, 2020 at 9:49
  • @TooTea what you described is called DCE (dead code elimination). But for gcc for example this is not the default behaviour as you can read here.
    – zomega
    Jun 2, 2020 at 11:01
  • Sorry, I should have been more clear. A static library is in fact just a collection of object files (.o). The linker will only include those object files that are needed to satisfy an undefined symbol. This is the core algorithm of ld, nothing to do with DCE (which is a compilation pass to eliminate parts of your own code that aren't used, long before the linker runs). Of course, if there are multiple routines in a single object file, some of them may be included unnecessarily (that can be avoided by using the non-default one-section-per-function layout).
    – TooTea
    Jun 2, 2020 at 11:46
  • @TooTea When you statically link you normally have a .a file (not .o). And default behaviour seems to be that the whole library will be in the executable. Also DCE is not limited to you own code.
    – zomega
    Jun 2, 2020 at 12:45
  • 3
    Right, but the .a file is just a bunch of .o files packed together. You can browse it with various general-purpose archiving tools, unpack/modify it using ar, etc.. Unless you supply the --whole-archive option to the linker, it will only use the .o's that are necessary. See a description of that option in man ld for details.
    – TooTea
    Jun 2, 2020 at 12:58
0

Linux (and later versions of Unix) support shared libraries. This is the big difference. A shared library is loaded in memory and is read only. If another program loads the same resource it simply gets a link to the existing in memory resource. This is why shared memory (.so) are fast, low memory usage and why static linked (think .a) programs are bigger in all ways. There are advantages to .a, but memory usage and program startup speed aren't among them. Not that this only applies to the code, not variables which are all in the user space. As for the standard library, chances are one of the early to load programs will use libc.so and almost every other program as well. That means it is in memory and only one copy of the code is needed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .