3

I want to know where the system call read() is. Which shared library is linked when I call read()?

3 Answers 3

4

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.

   ss of calls

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.

7
  • 1
    But 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.
    – Wyzard
    Mar 12, 2014 at 2:03
  • @Wyzard - reread my A that's exactly what I said at the top!
    – slm
    Mar 12, 2014 at 2:04
  • Point is, the wrapper function is in a shared library (specifically, libc). It's not right to say that no shared libraries are involved.
    – Wyzard
    Mar 12, 2014 at 2:05
  • @Wyzard - better?
    – slm
    Mar 12, 2014 at 2:30
  • Yeah, that's better.
    – Wyzard
    Mar 12, 2014 at 2:31
4

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).

2

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.

You must log in to answer this question.

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