vdso/gettimeofday.cThis is vdso/gettimeofday.c, an example to accompany the book, The Linux Programming Interface. This file is not printed in the book; it demonstrates Linux features that are not described in the book (typically features that have appeared since the book was published). The source code file is copyright 2024, Michael Kerrisk, and is licensed under the GNU General Public License, version 3. In the listing below, the names of Linux system calls and C library functions are hyperlinked to manual pages from the Linux man-pages project, and the names of functions implemented in the book are hyperlinked to the implementations of those functions.
|
/* gettimeofday.c A short program to demonstrate the benefits that the VDSO confers by replacing some traditional system calls with a user-space implementation in a shared library that is created by the kernel and mapped into the process's address space. Only certain system calls--those whose functionality can be performed entirely in user space--can be replaced with VDSO implementations; the vdso(7) manual page describes which functions are implemented in the VDSO on each Linux architecture. One system call that is commonly bypassed through an implementation in the VDSO is gettimeofday(2), which returns the current time. Obtaining the time on a computer is typically a matter of reading the value of a dedicated register (the "timestamp counter", TSC) or other hardware location. This operation can be performed from user space, but doing so requires machine-specific instructions and information, and we normally don't want to code such machine-specific dependencies into a user-space application. Thus, instead, the kernel (which by definition knows about every architecture) provides a system call that executes the necessary machine-specific code. With the existence of the VDSO, there is now an alternative: the kernel (which knows the machine specifics of accessing the TSC) can provide code in the VDSO that accesses the TSC. Since the VDSO is mapped into the process's user-space memory, the process can now access the TSC directly from user space (without itself containing any machine-specific code to perform that access). This program can be used to produce two binaries, one of which calls the gettimeofday() wrapper function in the C library while the other directly invokes the kernel system call using syscall(2). The choice is determined based on whether or not the USE_SYSCALL macro is defined. On systems (e.g., x86) where the kernel provides a VDSO implementation of gettimeofday() and the C library knows to use that implementation, obtaining the time will be a fast user-space operation. By contrast, when the system call is directly invoked via syscall(2) (a binary build with "cc -DUSE_SYSCALL"), obtaining the system time will be much slower. The program takes one command-line argument, which specifies the number times to loop fetching the system time. Try running the two different binaries with the same argument and timing the results using time(1). For example: time ./syscall_gettimeofday 10000000 time ./vdso_gettimeofday 10000000 */ #define _GNU_SOURCE /* See feature_test_macros(7) */ #include <sys/syscall.h> #include <sys/time.h> #include "tlpi_hdr.h"
int main(int argc, char *argv[]) { if (argc < 2 || strcmp(argv[1], "--help") == 0) usageErr("%s loop-count\n", argv[0]); long lim = atoi(argv[1]); for (int j = 0; j < lim; j++) { struct timeval curr; #ifdef USE_SYSCALL if (syscall(__NR_gettimeofday, &curr, NULL) == -1) errExit("gettimeofday"); #else if (gettimeofday(&curr, NULL) == -1) errExit("gettimeofday"); #endif } exit(EXIT_SUCCESS); }
Note that, in most cases, the programs rendered in these web pages are not free standing: you'll typically also need a few other source files (mostly in the lib/ subdirectory) as well. Generally, it's easier to just download the entire source tarball and build the programs with make(1). By hovering your mouse over the various hyperlinked include files and function calls above, you can see which other source files this file depends on.