I want to know where the system call read()
is. Which shared library is linked when I call read()?
3 Answers
The read()
function is implemented in a shared library (libc) which makes available wrapped functions into userspace. This exposes "access" to these functions which physically reside within the kernel.
You can convince yourself of this by taking a look at this diagram and noting that there are 2 tools for tracing these types of calls (system vs. shared library).
NOTE: In following diagram they're called strace
and ltrace
. See below for examples of the functions called by these tools, in the respective outputs from these 2 tools you can see what functions are being called by an executable, such as ls
.
Example
strace output:
$ strace -c ls
file1 file2
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.000017 1 18 mprotect
0.00 0.000000 0 8 read
0.00 0.000000 0 1 write
0.00 0.000000 0 10 open
0.00 0.000000 0 13 close
0.00 0.000000 0 1 stat
0.00 0.000000 0 11 fstat
0.00 0.000000 0 27 mmap
0.00 0.000000 0 2 munmap
0.00 0.000000 0 3 brk
0.00 0.000000 0 2 rt_sigaction
0.00 0.000000 0 1 rt_sigprocmask
0.00 0.000000 0 2 ioctl
0.00 0.000000 0 1 1 access
0.00 0.000000 0 1 execve
0.00 0.000000 0 2 getdents
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 2 statfs
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 openat
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.000017 110 1 total
ltrace output:
$ ltrace -c ls
file1 file2
% time seconds usecs/call calls function
------ ----------- ----------- --------- --------------------
11.42 0.001012 84 12 __ctype_get_mb_cur_max
11.24 0.000996 124 8 getenv
10.54 0.000934 93 10 __errno_location
9.96 0.000883 98 9 malloc
6.03 0.000534 106 5 memcpy
5.99 0.000531 106 5 readdir
4.60 0.000408 408 1 setlocale
3.77 0.000334 83 4 free
3.70 0.000328 82 4 __freading
3.26 0.000289 96 3 __overflow
2.95 0.000261 87 3 strlen
2.66 0.000236 118 2 fclose
2.46 0.000218 109 2 fwrite_unlocked
2.05 0.000182 182 1 strrchr
1.90 0.000168 84 2 __fpending
1.87 0.000166 83 2 fflush
1.87 0.000166 83 2 fileno
1.52 0.000135 135 1 isatty
1.43 0.000127 127 1 getopt_long
1.41 0.000125 125 1 ioctl
1.35 0.000120 120 1 textdomain
1.35 0.000120 120 1 bindtextdomain
1.29 0.000114 114 1 opendir
1.22 0.000108 108 1 closedir
1.21 0.000107 107 1 __cxa_atexit
1.05 0.000093 93 1 strcoll
0.95 0.000084 84 1 realloc
0.94 0.000083 83 1 _setjmp
------ ----------- ----------- --------- --------------------
100.00 0.008862 86 total
So where's read()?
If you notice in the output read
is listed as a function in the strace
output, not the ltrace
output. This is because it's part of the system call interface.
-
1But the program isn't directly invoking the system call; that involves special machine code that you can't express in C. The program is instead calling a C wrapper for the system call, and the wrapper is a library function.– WyzardMar 12, 2014 at 2:03
-
-
Point is, the wrapper function is in a shared library (specifically, libc). It's not right to say that no shared libraries are involved.– WyzardMar 12, 2014 at 2:05
-
-
The raw system calls, like read(2)
, are defined in the C library (usually glibc under Linux). But what the definition in the library does is just to collect arguments, set them up for the special way in which they are passed to the kernel, and use a special mechanism to ask the kernel to do the job. It collects the results (including possible error indications) and translates them into the value returned by the call.
In general, if you want to know about function foo
, man foo
should answer your question. The header of the manual page should say e.g. foo(2)
or foo(3)
or similar. The number 2 means system call, 3 means library function. In the rare case another number shows, try man 2 foo
and man 3 foo
.
System calls are defined in the C library (and the job is done by the kernel); library functions are defined in libraries, the manual page should tell what libraries to use (by citing some -l<something>
flags to link, then it is in the <something>
library).
System calls are implemented in the kernel — that's why they're called "system" calls — but the mechanism for invoking a system call in the kernel is platform-specific and may involve special assembly instructions, so programs typically don't do this directly.
The system's C library (libc) provides wrapper functions for system calls. These are ordinary userspace functions that you can call like any other C function, and they perform the necessary magic to delegate to the real system call in the kernel.