Is There a Libc in Kernel Space

Is shared standard C library first initialized by kernel?

You are wrong.

1.) There is no need to put libc into kernel. It doesn't affect any low-level system or hardware dependent components.

2.) libc.so is ordinary dynamic library.

Now some more details:

When you launch your application, f.e. from bash console, bash forks and execs new process. What does it mean. Actually, this means that OS creates address space environment and loads .text .data .bss from ELF file, preserves virtual space for stack. You can see this mappings here:

sudo cat /proc/1118/maps 
00400000-00407000 r-xp 00000000 08:01 1845158 /sbin/getty
00606000-00607000 r--p 00006000 08:01 1845158 /sbin/getty
00607000-00608000 rw-p 00007000 08:01 1845158 /sbin/getty
00608000-0060a000 rw-p 00000000 00:00 0
00ff3000-01014000 rw-p 00000000 00:00 0 [heap]
...
7f728efd3000-7f728efd5000 rw-p 001bf000 08:01 466797 /lib/x86_64-linux-gnu/libc-2.19.so
7f728efd5000-7f728efda000 rw-p 00000000 00:00 0
7f728efda000-7f728effd000 r-xp 00000000 08:01 466799 /lib/x86_64-linux-gnu/ld-2.19.so

7f728f1fe000-7f728f1ff000 rw-p 00000000 00:00 0
7fffa122b000-7fffa124c000 rw-p 00000000 00:00 0 [stack]
7fffa1293000-7fffa1295000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

But there are more. After loading thoose segments, Linux kernel will also load ld-linux.so into memory (you can see it in mappings). This stuff called dynamic linker, and actually ld-linux is responsible for all dynamic libraries loading. As you might know, at the moment the application have been compiled, you already know the list of shared libraries you will use. You can check it via ldd command

ldd /sbin/getty 
linux-vdso.so.1 => (0x00007fff4cfa6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2af2832000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2af2c24000)

This stuff must be held somewhere in the ELF (don't know where exactly). So after loading, ld-linux uses this list and finds all needed libraries at predefined (standart) paths like /usr/lib and so on. Now ld-linux can just mmap regions for located dynamic libraries. That is how libc will be loaded to process address space.

user space library in Linux kernel modal - for testing

A C library is first of all a collection of functions, there is no real distinction between "user-space" and "kernel-space". However, using a dynamic shared library is not straight possible in kernel space, since there is no suitable dynamic loader for this. Indeed, loading the kernel-module itself is some kind of dynamic loading, but the module itself cannot load another shared library in turn.

However, it should be possible to link code from a static library (.a) to your kernel module. This code then becomes integral part of your kernel module itself and should work in kernelspace as in userspace, as long as it doesn't depend on external symbols, which are not present in kernel space (especially symbols of the libc, for example).

Are system calls directly send to the kernel?

It might not be the same on Linux and on some other POSIX system (like FreeBSD).

On Linux, the ABI defines how a system call is done. Read about Linux kernel interfaces. The system calls are listed in syscalls(2) (but see also /usr/include/asm*/unistd.h ...). Read also vdso(7). The assembler HowTo explains more details, but for 32 bits i686 only.

Most Linux libc are free software, you can study their source code. IMHO the source code of musl-libc is very readable.

To simplify a tiny bit, most system calls (e.g. write(2)) are small C functions in the libc which:

  1. call the kernel using SYSENTER machine instruction (and take care of passing the system call number and its arguments with the kernel convention, which is not the usual C ABI). What the kernel considers as a system call is only that machine instruction (and conventions about it).

  2. handle the failure case, by passing it to errno(3) and returning -1.

    (IIRC, on failure, the carry -or perhaps the overflow- flag bit is set when the kernel returns from SYSENTER; but I could be wrong in the details)

  3. handle the success case, by returning a result.

You could invoke system calls without libc, with some assembler code. This is unusual, but has been done (e.g. in BusyBox or in Bones).

So the libc code for write is doing some tiny extra work (passing arguments, handling failure & errno and success cases).

Some few system calls (probably getpid & clock_gettime) avoid the overhead of the SYSENTER machine instruction (and user-mode -> kernel-mode switch) thanks to vDSO.

Why can't we use C standard library functions in kernel development?

Because the GNU C Library which you are familiar with is implemented for user mode, not kernel mode. The kernel cannot access a userspace API (which might invoke a syscall to the Linux kernel).

From the KernelNewbies FAQ

Can I use library functions in the kernel ?

System libraries (such as glibc, libreadline, libproplist, whatever) that are typically available to userspace programmers are unavailable to kernel programmers. When a process is being loaded the loader will automatically load any dependent libraries into the address space of the process. None of this mechanism is available to kernel programmers: forget about ISO C libraries, the only things available is what is already implemented (and exported) in the kernel and what you can implement yourself.

Note that it is possible to "convert" libraries to work in the kernel; however, they won't fit well, the process is tedious and error-prone, and there might be significant problems with stack handling (the kernel is limited to a small amount of stack space, while userspace programs don't have this limitation) causing random memory corruption.

Many of the commonly requested functions have already been implemented in the kernel, sometimes in "lightweight" versions that aren't as featureful as their userland counterparts. Be sure to grep the headers for any functions you might be able to use before writing your own version from scratch. Some of the most commonly used ones are in include/linux/string.h.

Whenever you feel you need a library function, you should consider your design, and ask yourself if you could move some or all the code into user-space instead.

If you need to use functions from standard library, you have to re-implement that functionality because of a simple reason - there is no standard C library.

C library is basically implemented on the top of the Linux kernel (or other operating system's kernel).

For instance, C library's mkdir(3) function is basically nothing more than a wrapper for Linux kernel's system call mkdir(2).

http://linux.die.net/man/3/mkdir
http://linux.die.net/man/2/mkdir

Is there a list of functions that I can use inside kernel?

Probably the biggest difference (among many big differences) that you will need to get your head around is this: the kernel is not linked against libc. So, look at everything provided by libc. you don't get any of that...

...well, sort of. Some of the functionality that libc provides is actually implemented inside the kernel itself. You need to include the kernel versions of those headers:

#include <linux/[header file].h>

To get an idea of what is available inside the kernel, you'll need to look at the functions defined in the header files of the kernel source tree.

A few other points to keep in mind:

  • Linux kernel is programmed using GNU C, not strict ANSI C, which makes sense: as some folks would be quick to point out, Linux is just the kernel, GNU is everything else; that includes the GCC compiler.
  • No easy floating point math. Normally the kernel facilitates the use of floating point instructions, but the mechanism it uses to that cannot be easily used on the kernel itself. See here for more.

A good book on the subject is Linux Kernel Development by Robert Love (I am in no way affiliated; it's just a good book).



Related Topics



Leave a reply



Submit