Linux system programming cheatsheet

A very dense reference of man pages excerpts I put together to remember what’s what in the Linux (mostly POSIX) system programming.

Errors

extern int errno; // NB: shared by all threads!

#include <stdio.h>
void perror (const char *str);
    // prints descrption of errno to stderr prefixed with 'str'

#include <string.h>
char * strerror (int errnum); // NB: returns static memory!
int strerror_r (int errnum, char *buf, size_t len);

Files

Low (syscall) level

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open (const char *name, int flags);
int open (const char *name, int flags, mode_t mode);
int close (int fd);

int creat (const char *name, mode_t mode);

ssize_t read (int fd, void *buf, size_t len);
ssize_t write (int fd, const void *buf, size_t count);

int dup(int oldfd); // copy file descriptor oldfd to lowest-numbered unused fd
int dup2(int oldfd, int newfd); // copy oldfd to (silently atomically  closed) newfd

#include <sys/types.h>
#include <unistd.h>
off_t lseek (int fd, off_t pos, int origin); // SEEK_CUR, SEEK_END, SEEK_SET

int ftruncate (int fd, off_t len);
int truncate (const char *path, off_t len);

#include <unistd.h>
int fsync (int fd); // flush modified page cache to disk
int fdatasync (int fd); // faster; no metadata, only file contents
void sync (void); // on Linux, doesn't return until all page cache flushed

// There are also related flags for open(): 
//   O_SYNC (fsync after write) and 
//   O_DIRECT (don't use page cache, all i/o ops sync'ed)

#define _XOPEN_SOURCE 500
#include <unistd.h>
ssize_t pread (int fd, void *buf, size_t count, off_t pos);
ssize_t pwrite (int fd, const void *buf, size_t count, off_t pos);
    // Don't update current position within the file

Multiplexing

Wait for file descriptors to become ready for reading/writing.

#include <sys/select.h>
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 
	    struct timeval *timeout);
// See also fd_set manipulation routines:
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);

#include <poll.h>
int poll (struct pollfd *fds, nfds_t nfds, int timeout);

Pipes

#include <unistd.h>
int pipe(int pipefd[2]); // pipefd[0] - read end, [1] - write end

#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
int pipe2(int pipefd[2], int flags);
    // flags: O_CLOEXEC, O_DIRECT ("packet" mode), O_NONBLOCK


#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <fcntl.h>
ssize_t splice(int fd_in, loff_t *off_in, int fd_out,
                      loff_t *off_out, size_t len, unsigned int flags);
    // moves data from the buffer to an arbitrary file descriptor, 
    // or vice versa, or from one buffer to another.
    // flags: SPLICE_F_MOVE, SPLICE_F_NONBLOCK, SPLICE_F_MORE

ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);
    // "copies" the data from one buffer to another.

#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <fcntl.h>
#include <sys/uio.h>
ssize_t vmsplice(int fd, const struct iovec *iov,
		 unsigned long nr_segs, unsigned int flags);
    // "copies" data from user space into the buffer.
    // flags: SPLICE_F_NONBLOCK, SPLICE_F_GIFT

Standard I/O

Uses an additional user-space buffer (see setvbuf() below), so may be slower than other methods, albeit more convenient in some cases.

#include <stdio.h>
FILE * fopen (const char *path, const char *mode); 
    // mode: "r", "r+", "w", "w+", "a", "a+"

FILE * fdopen (int fd, const char *mode);
    // NB: mode must be compatible with the opened fd

int fclose(FILE*stream);

#define _GNU_SOURCE
#include <stdio.h>
int fcloseall(void);

int fgetc(FILE*stream);
char * fgets (char *str, int size, FILE *stream); // read string up to (size-1)
    // See also LINE_MAX defined <limits.h> by POSIX.
size_t fread (void *buf, size_t size, size_t nr, FILE *stream);
    // Read data reads nmemb items of data, each size bytes long

int fputc (int c, FILE *stream); // write one char
size_t fwrite (void *buf, size_t size, size_t nr, FILE *stream);
    // Write nmemb items of data, each size bytes long

int fseek (FILE *stream, long offset, int whence);
int fsetpos(FILE*stream, fpos_t*pos);
void rewind (FILE *stream); // == fseek (stream, 0, SEEK_SET);
    // Change "current position" within the file

long ftell (FILE *stream); // current position
int fgetpos(FILE*stream, fpos_t*pos); // writes cur position to 'pos'

int fflush (FILE *stream); // just flushes to the kernel cache, not disk

int ferror(FILE*stream);
int feof(FILE*stream); // is EOF?
void clearerr(FILE*stream);

int fileno(FILE*stream); // returns file descriptor for syscalls

int setvbuf (FILE *stream, char *buf, int mode, size_t size);
    // Sets buffering mode:
    // _IONBF - no buffering, _IOLBF - line buf, _IOFBF - block size buf

Thread Safety

// Note: all the above operations already atomic; below is needed for multiple
// consequtive calls only

#include <stdio.h>

void flockfile (FILE *stream); 
void funlockfile (FILE*stream);
int ftrylockfile (FILE*stream);

// Those are faster, but no thread safety at all; not part of POSIX:
#define _GNU_SOURCE
#include <stdio.h>
int fgetc_unlocked (FILE *stream);
char *fgets_unlocked (char *str, int size, FILE *stream);
size_t fread_unlocked (void *buf, size_t size, size_t nr, FILE *stream);
int fputc_unlocked (int c, FILE *stream);
int fputs_unlocked (const char *str, FILE *stream);
size_t fwrite_unlocked (void *buf, size_t size, size_t nr, FILE *stream);
int fflush_unlocked (FILE *stream);
int feof_unlocked (FILE *stream);
int ferror_unlocked (FILE *stream);
int fileno_unlocked (FILE *stream);
void clearerr_unlocked (FILE *stream);

Extended I/O (syscalls)

#include <sys/uio.h>
// Read/write from several buffers
ssize_t readv (int fd, const struct iovec *iov, int count);
ssize_t writev (int fd, const struct iovec *iov, int count);
    struct iovec {
	void  *iov_base;    /* Starting address */
	size_t iov_len;     /* Number of bytes to transfer */
    };
    // Read/write multiple buffers at once

#include <sys/epoll.h>
int epoll_create1 (int flags);
int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout);

#include <sys/mman.h>
void * mmap (void *addr, size_t len, int prot, int flags,int fd, off_t offset);
    // prot: PROT_NONE, PROT_READ, PROT_WRITE, PROT_EXEC
    // flags: MAP_FIXED, MAP_PRIVATE, MAP_SHARED
int munmap (void *addr, size_t len);
void * mremap (void *addr, size_t old_size, size_t new_size, unsigned long flags);
    // Maps/unmap file to/from memory. No other caches are involved.

See also:

    #include <unistd.h>
    long page_size = sysconf (_SC_PAGESIZE);
    int getpagesize (void);

    #include <sys/user.h>
    int page_size= PAGE_SIZE; // obviously defined at compile time
int mprotect (const void *addr, size_t len, int prot); // see above for 'prot'
int msync (void *addr, size_t len, int flags); // flush to disk
    // flags: MS_SYNC (wait for complete), MS_ASYNC, 
    // MS_INVALIDATE (other mappings, so others see new data)
int madvise (void *addr, size_t len, int advice); // advice to kernel
    // advice: MADV_NORMAL, MADV_RANDOM, MADV_SEQUENTIAL, MADV_WILLNEED,
    // MADV_DONTNEED, MADV_DONTFORK, MADV_DOFORK, MADV_DONTDUMP, MADV_DODUMP,
    // MADV_FREE, MADV_WIPEONFORK, MADV_KEEPONFORK

#include <fcntl.h>
int posix_fadvise (int fd, off_t offset, off_t len, int advice);
    // advice: POSIX_FADV_NORMAL, POSIX_FADV_RANDOM, POSIX_FADV_SEQUENTIAL, 
    // POSIX_FADV_WILLNEED, POSIX_FADV_NOREUSE, POSIX_FADV_DONTNEED

File metadata

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat (const char *path, struct stat *buf);
int fstat (int fd, struct stat *buf);
int lstat (const char *path, struct stat *buf);

struct stat {
   dev_t     st_dev;         /* ID of device containing file */
   ino_t     st_ino;         /* Inode number */
   mode_t    st_mode;        /* File type and mode */
   nlink_t   st_nlink;       /* Number of hard links */
   uid_t     st_uid;         /* User ID of owner */
   gid_t     st_gid;         /* Group ID of owner */
   dev_t     st_rdev;        /* Device ID (if special file) */
   off_t     st_size;        /* Total size, in bytes */
   blksize_t st_blksize;     /* Block size for filesystem I/O */
   blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

   struct timespec st_atim;  /* Time of last access */
   struct timespec st_mtim;  /* Time of last modification */
   struct timespec st_ctim;  /* Time of last status change */
};

#include <sys/types.h>
#include <sys/stat.h>
int chmod (const char *path, mode_t mode);
int fchmod (int fd, mode_t mode);

int chown (const char *path, uid_t owner, gid_t group);
int lchown (const char *path, uid_t owner, gid_t group);
int fchown (int fd, uid_t owner, gid_t group);

Extended attributes (support depends on FS)

Manage arbitrary string key/value pairs for files stored with the file metadata.

#include <sys/types.h>
#include <attr/xattr.h>
ssize_t getxattr (const char *path, const char *key, void *value, size_t size);
ssize_t lgetxattr (const char *path, const char *key, void *value, size_t size);
ssize_t fgetxattr (int fd, const char *key, void *value, size_t size);

int setxattr (const char *path, const char *key, const void *value, size_t size, int flags);
int lsetxattr (const char *path, const char *key, const void *value, size_t size, int flags);
int fsetxattr (int fd, const char *key, const void *value, size_t size, int flags);

ssize_t listxattr (const char *path,290 char *list, size_t size); 
ssize_t llistxattr (const char *path, char *list, size_t size);
ssize_t flistxattr (int fd, char *list, size_t size);

int removexattr (const char *path, const char *key);
int lremovexattr (const char *path, const char *key);
int fremovexattr (int fd, const char *key);

Directories

#include <unistd.h>
char * getcwd (char *buf, size_t size); // See also BUF_LEN

#define _GNU_SOURCE
#include <unistd.h>
char * get_current_dir_name (void);

#include <unistd.h>
int chdir (const char *path);
int fchdir (int fd);

#include <sys/stat.h>
#include <sys/types.h>
int mkdir (const char *path, mode_t mode);

#include <unistd.h>
int rmdir (const char *path);

#include <sys/types.h>
#include <dirent.h>
DIR * opendir (const char *name);
struct dirent * readdir (DIR *dir);
int closedir (DIR *dir);

int link (const char *oldpath, const char *newpath);
int unlink (const char *pathname);
int rename (const char *oldpath, const char *newpath);

Devices

  • /dev/null
  • /dev/zero
  • /dev/full (ENOSPC on write)
  • /dev/urandom
  • /dev/random (more random, but can block for a long time!)
#include <sys/ioctl.h>
int ioctl (int fd, int request, ...); // talk directly to special files

Filesystem events

#include <sys/inotify.h>
int inotify_init1 (int flags);
    // flags: IN_CLOEXEC, IN_NONBLOCK

int inotify_add_watch (int fd, const char *path, uint32_t mask);
    // fd: from above call 
    // mask: (for files) IN_ACCESS, IN_MODIFY, IN_ATTRIB, IN_CLOSE_WRITE,
    // IN_CLOSE_NOWRITE, IN_OPEN, 
    // (for dirs) IN_MOVED_FROM, IN_MOVED_TO, IN_CREATE, IN_DELETE, 
    // IN_DELETE_SELF, IN_MOVE_SELF
    // IN_ALL_EVENTS, IN_CLOSE, IN_MOVE
int inotify_rm_watch (int fd, uint32_t wd);

struct inotify_event {
    int wd;
    uint32_t mask;
    uint32_t cookie;
    uint32_t len;
    char name[];
};

Obtain events by reading from fd. Example:

char buf[BUF_LEN] __attribute__((aligned(4)));
len = read (fd, buf, BUF_LEN);
struct inotify_event *event = (struct inotify_event *) &buf[i];
i += sizeof (struct inotify_event) + event->len

ret = ioctl (fd, FIONREAD, &queue_len); // size of events queue

close(fd); // fd is from inotify_init()

Processes

#include <sys/types.h>
#include <unistd.h>
pid_t getpid (void); // pid of self
pid_t getppid (void); // pid of parent

#include<unistd.h>
int execl (const char *path, const char *arg, ...);
int execlp (const char *file, const char *arg, ...);
int execle (const char *path, const char *arg, ..., char * const envp[]);
int execv (const char *path, char *const argv[]);
int execvp (const char *file, char *const argv[]);
int execve (const char *filename, char *const argv[], char *const envp[]);
    // l - args passed as list, v - as array, p - command searched in $PATH

#include <sys/types.h>
#include <unistd.h>
pid_t fork (void);
pid_t vfork (void); // child has no separate addr. space; exec immediately

#include <stdlib.h>
void exit (int status); // returns (status & 0377) to parent process
int atexit (void (*function)(void));

See also EXIT_SUCCESS and EXIT_FAILURE

#include<sys/types.h>
#include <sys/wait.h>
pid_t wait (int *status);
pid_t waitpid (pid_t pid, int *status, int options);
    // options: WNOHANG, WUNTRACED, WCONTINUED
int WIFEXITED (status);
    // ... and WIFSIGNALED, WIFSTOPPED, WIFCONTINUED, WEXITSTATUS, WTERMSIG, 
    // WSTOPSIG, WCOREDUMP

int waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options);
    // options: WEXITED, WSTOPPED, WCONTINUED, WNOHANG, WNOWAIT

// Get resource usage (time, page faults, context switches, etc):
pid_t wait3 (int *status, int options, struct rusage *rusage);
pid_t wait4 (pid_t pid, int *status, int options, struct rusage *rusage);

#define _XOPEN_SOURCE
#include <stdlib.h>
int system (const char *command); // fork/execl a shell that will execute 'command'

Users/groups

Manage effective user/group ID of the current(calling) process.

#include <sys/types.h>
#include <unistd.h>
int setuid (uid_t uid);
int setgid (gid_t gid);

int seteuid (uid_t euid); // set effective ID only
int setegid (gid_t egid);

uid_t getuid (void); // real user ID
gid_t getgid (void);

uid_t geteuid (void); // effective user ID
gid_t getegid (void);

#include<unistd.h>
pid_t setsid (void); // start new session with self as leader, clears control tty
pid_t getsid (pid_t pid);

#define _XOPEN_SOURCE 500
#include <unistd.h>
int setpgid (pid_t pid, pid_t pgid); // sets process group ID
pid_t getpgid (pid_t pid);

int daemon (int nochdir, int noclose);
    // make self daemon (no tty, all std IO to /dev/null)

Scheduling

#include<sched.h>
int sched_yield(void); // rarely needed; the kernel is preemptive

#include <unistd.h>
int nice (int inc); 
    // how nicer we are to the other processes on the system
    // nice(0) - current value

#include <sys/time.h>
#include <sys/resource.h>
int getpriority (int which, int who);
int setpriority (int which, int who, int prio);
    // which: PRIO_PROCESS, PRIO_PGRP or PRIO_USER (determines meaning of who)

#define _GNU_SOURCE
#include <sched.h>
int sched_setaffinity (pid_t pid, size_t setsize, const cpu_set_t *set);
int sched_getaffinity (pid_t pid, size_t setsize, cpu_set_t *set);
#include <sys/time.h>
#include <sys/resource.h>
int getrlimit (int resource, struct rlimit *rlim);
int setrlimit (int resource, const struct rlimit *rlim);
    // resource: RLIMIT_AS, RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA,
    // RLIMIT_FSIZE, RLIMIT_LOCKS, RLIMIT_MEMLOCK, RLIMIT_MSGQUEUE,
    // RLIMIT_NICE, RLIMIT_NOFILE, RLIMIT_NPROC, RLIMIT_RSS, 
    // LIMIT_RTTIME, LIMIT_RTPRIO, LIMIT_SIGPENDING, RLIMIT_STACK

PThreads

NB: compile with ‘gcc -pthread’

#include <pthread.h>
int pthread_create (pthread_t *thread, const pthread_attr_t *attr,
		    void *(*start_routine) (void *), void *arg);

pthread_t pthread_self (void);
int pthread_equal (pthread_t t1, pthread_t t2);

void pthread_exit (void *retval);

int pthread_cancel (pthread_t thread);
int pthread_setcanceltype (int type, int *oldtype);
    // type: PTHREAD_CANCEL_DEFERRED (until cancellation point),
    // PTHREAD_CANCEL_ASYNCHRONOUS (anytime)
int pthread_setcancelstate(int state, int *oldstate);
    // state: PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE

int pthread_join (pthread_t thread, void **retval);
int pthread_detach (pthread_t thread); // to free resources if not joinable

Mutexes

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock (pthread_mutex_t *mutex);
int pthread_mutex_unlock (pthread_mutex_t *mutex);

Memory management

Memory allocation

#include <stdlib.h>
void * malloc (size_t size);
void * calloc (size_t nr, size_t size); // nr*size, zero-initialized
void * realloc (void *ptr, size_t size);
void free (void *ptr);

#define _GNU_SOURCE
#include <stdlib.h>
int posix_memalign (void **memptr, size_t alignment, size_t size);
    // Allocates aligned space
#include <malloc.h>
int mallopt (int param, int value); // call before the first malloc!
    // Configures heap management.
    // param: M_CHECK_ACTION, M_MMAP_MAX, M_MMAP_THRESHOLD, M_MXFAST,
    // M_PERTURB, M_TOP_PAD, M_TRIM_THRESHOLD

size_t malloc_usable_size (void *ptr); // how much has actually been allocated
int malloc_trim (size_t padding);

See also MALLOC_CHECK_ env var (for instance, MALLOC_CHECK_=7)

struct mallinfo mallinfo (void); // heap info (see below)
   struct mallinfo {
       int arena;     /* Non-mmapped space allocated (bytes) */
       int ordblks;   /* Number of free chunks */
       int smblks;    /* Number of free fastbin blocks */
       int hblks;     /* Number of mmapped regions */
       int hblkhd;    /* Space allocated in mmapped regions (bytes) */
       int usmblks;   /* Maximum total allocated space (bytes) */
       int fsmblks;   /* Space in freed fastbin blocks (bytes) */
       int uordblks;  /* Total allocated space (bytes) */
       int fordblks;  /* Total free space (bytes) */
       int keepcost;  /* Top-most, releasable space (bytes) */
   };

void malloc_stats (void); // print above stats to stderr
#include <unistd.h>
int brk (void *end); // shift data segment to end
void * sbrk (intptr_t increment); // shift data segment by increment
    // sbrk(0) - current segment end

#include <sys/mman.h>
void * mmap (void *start, size_t length, int prot, int flags, int fd, 
	     off_t offset);
    // flags = MAP_ANONYMOUS | MAP_PRIVATE => zero-initialized, fd ignored
    // length multiple of page size
int munmap (void *start, size_t length);
#include <alloca.h>
void * alloca (size_t size); // allocate on stack, no need to free, not POSIX

#define _GNU_SOURCE
#include <string.h>
char * strdupa (const char *s); // alloca()'d space
char * strndupa (const char *s, size_t n); // alloca()'d space

Memory manipulation

#include <string.h>
void * memset (void *s, int c, size_t n);
void bzero (void *s, size_t n);

int memcmp (const void *s1, const void *s2, size_t n);

void * memmove (void *dst, const void *src, size_t n);

void * memchr (const void *s, int c, size_t n);

void * memmem (const void *haystack, size_t haystacklen, 
	       const void *needle, size_t needlelen);

#define _GNU_SOURCE
#include <string.h>
void * memfrob (void *s, size_t n); // XOR 42 for "security"

#include <sys/mman.h>
int mlock (const void *addr, size_t len); // don't flush this memory to disk
int mlockall (int flags);
    // flags: MCL_CURRENT (only current pages), MCL_FUTURE (all pages)
int munlock (const void *addr, size_t len);
int munlockall (void);

#include <unistd.h>
#include <sys/mman.h>
int mincore (void *start, size_t length, unsigned char *vec);
    // whether pages in memory or on disk

Signals

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal (int signo, sighandler_t handler); // set signal handler
    // handler: user func or SIG_DFL, SIG_IGN

#include <unistd.h>
int pause (void); // wait for any signal
#include <sys/types.h>
#include <signal.h>
int kill (pid_t pid, int signo); // send signo to pid

int raise (int signo); // == kill(getpid(), signo), send to self

int killpg (int pgrp, int signo); // == kill(-pgrp, signo), send to group
extern const char * const sys_siglist[]; // human-readable signal name by num

#define _GNU_SOURCE
#include <string.h>
char * strsignal (int signo); // human-readable signal name by num

Signal sets

#include <signal.h>
int sigemptyset (sigset_t *set);
int sigfillset (sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset (sigset_t *set, int signo);
int sigismember (const sigset_t *set, int signo);

#define _GNU_SOURCE
#define <signal.h>
int sigisemptyset (sigset_t *set);
int sigorset (sigset_t *dest, sigset_t *left, sigset_t *right);
int sigandset (sigset_t *dest, sigset_t *left, sigset_t *right);

#include <signal.h>
int sigprocmask (int how, const sigset_t *set, sigset_t *oldset);
    // how: SIG_SETMASK, SIG_BLOCK, SIG_UNBLOCK

int sigpending (sigset_t *set);
    // the set of signals that are pending for delivery (raised while blocked)

int sigsuspend (const sigset_t *set); // suspend until sig from set

Extended signals

int sigaction (int signo, const struct sigaction *act,
	       struct sigaction *oldact);

struct sigaction {
   void     (*sa_handler)(int);
   void     (*sa_sigaction)(int, siginfo_t *, void *);
   sigset_t   sa_mask;
   int        sa_flags; // SA_NOCLDSTOP, SA_NOCLDWAIT, SA_NODEFER,
		        // SA_ONSTACK, SA_RESETHAND, SA_RESTART, SA_SIGINFO
   void     (*sa_restorer)(void);
};

siginfo_t {
   int      si_signo;     /* Signal number */
   int      si_errno;     /* An errno value */
   int      si_code;      /* Signal code */
   int      si_trapno;    /* Trap number that caused
			     hardware-generated signal
			     (unused on most architectures) */
   pid_t    si_pid;       /* Sending process ID */
   uid_t    si_uid;       /* Real user ID of sending process */
   int      si_status;    /* Exit value or signal */
   clock_t  si_utime;     /* User time consumed */
   clock_t  si_stime;     /* System time consumed */
   sigval_t si_value;     /* Signal value */
   int      si_int;       /* POSIX.1b signal */
   void    *si_ptr;       /* POSIX.1b signal */
   int      si_overrun;   /* Timer overrun count; POSIX.1b timers */
   int      si_timerid;   /* Timer ID; POSIX.1b timers */
   void    *si_addr;      /* Memory location which caused fault */
   long     si_band;      /* Band event */
   int      si_fd;        /* File descriptor */
   short    si_addr_lsb;  /* Least significant bit of address */
   void    *si_lower;     /* Lower bound when address violation occurred */
   void    *si_upper;     /* Upper bound when address violation occurred */
   int      si_pkey;      /* Protection key on PTE that caused fault */
   void    *si_call_addr; /* Address of system call instruction */
   int      si_syscall;   /* Number of attempted system call */
   unsigned int si_arch;  /* Architecture of attempted system call */
};

int sigqueue (pid_t pid, int signo, const union sigval value); 
    // sends a signal with payload
    union sigval {
	int sival_int;
	void *sival_ptr;
    };

Time

hz = sysconf (_SC_CLK_TCK); // tick per second (for ex.: 100, 250, 300, 1000)
#include <sys/time.h>
struct timeval {
    time_t tv_sec;
    suseconds_t tv_usec; // microseconds
};

struct timespec {
    time_t tv_sec; 
    long tv_nsec; // nanoseconds
};

#include <time.h>
struct tm {
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst; /* DST? */
#ifdef _BSD_SOURCE
    long tm_gmtoff;
    const char *tm_zone;
#endif /* _BSD_SOURCE */
};

clockid_t:

  • CLOCK_REALTIME - wall clock, can be changed by root (resolution: ticks)
  • CLOCK_MONOTONIC - time since, for ex., last boot; can’t be adjusted (ticks)
  • CLOCK_MONOTONIC_RAW - same as above(?); Linux-specific (resolution: ticks)
  • CLOCK_PROCESS_CPUTIME_ID - hi-res (nanosec) CPU clock
  • CLOCK_THREAD_CPUTIME_ID - per-thread hi-res (nanosec) CPU clock
#include <time.h>
int clock_getres (clockid_t clock_id, struct timespec *res);

#include <time.h>
time_t time (time_t *t); // current time

struct timeval tv;
int ret;
ret = gettimeofday (&tv, NULL); // current time with microsecond precision

int clock_gettime (clockid_t clock_id, struct timespec *ts);
#include <sys/times.h>
clock_t times(struct tms *buf); // process time
    struct tms {
       clock_t tms_utime;  /* user time */
       clock_t tms_stime;  /* system time */
       clock_t tms_cutime; /* user time of children */
       clock_t tms_cstime; /* system time of children */
    };
#define _SVID_SOURCE
#include <time.h>
int stime (time_t *t); // set current time (requires CAP_SYS_TIME)

#include <sys/time.h>
int settimeofday (const struct timeval *tv, const struct timezone *tz);
    // tz better be NULL

#include <time.h>
int clock_settime (clockid_t clock_id, const struct timespec *ts);
    // supposed to work only for CLOCK_REALTIME
#include <time.h>
char * asctime (const struct tm *tm); // NB: returns static memory!
char * asctime_r (const struct tm *tm, char *buf);

char * ctime (const time_t *timep);
char * ctime_r (const time_t *timep, char *buf);

time_t mktime (struct tm *tm); // converts to time_t (usually long)

struct tm * gmtime (const time_t *timep); // NB: returns static memory!
struct tm * gmtime_r (const time_t *timep, struct tm *result);
    // Convert time assuming UTC

struct tm * localtime (const time_t *timep); // NB: returns static memory!
struct tm * localtime_r (const time_t *timep, struct tm *result);
    // Convert time assuming current timezone

double difftime (time_t time1, time_t time0);

Adjust time

#define _BSD_SOURCE
#include <sys/time.h>
int adjtime (const struct timeval *delta, struct timeval *olddelta);
    // Slowly adjust time by changing system clock tick intervals

#include <sys/timex.h>
int adjtimex (struct timex *adj); // see ADJTIMEX(2)

Sleeping

#include <unistd.h>
unsigned int sleep (unsigned int seconds); // returns secs NOT in sleep

#include <unistd.h>
int usleep (useconds_t usec); // microsecond precision

#define _POSIX_C_SOURCE 199309
#include <time.h>
int nanosleep (const struct timespec *req, struct timespec *rem);

#include <time.h>
int clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
		     struct timespec *rem);

// Or use select() to wait (microseconds precision):
#include <sys/select.h>
int select (int, fd_set *, fd_set *, fd_set *, struct timeval *timeout);

select (0, NULL, NULL, NULL, &tv); // Only tv is important

Alarms

#include <unistd.h>
unsigned int alarm (unsigned int seconds); // SIGALRM after 'seconds'

#include <sys/time.h>
int getitimer (int which, struct itimerval *value);
int setitimer (int which, const struct itimerval *value, 
	       struct itimerval *ovalue);
    // which: ITIMER_REAL, ITIMER_VIRTUAL (proc in user-space),
    // ITIMER_PROF (proc on CPU), ITIMER_REAL (same as alarm())

   struct itimerval {
       struct timeval it_interval; /* Interval for periodic timer */
       struct timeval it_value;    /* Time until next expiration */
   };

   struct timeval {
       time_t      tv_sec;         /* seconds */
       suseconds_t tv_usec;        /* microseconds */
   };
#include <signal.h>
#include <time.h>
int timer_create (clockid_t clockid, struct sigevent *evp, timer_t *timerid);
int timer_delete (timer_t timerid);
    struct sigevent {
	union sigval sigev_value;
	int sigev_signo;
	int sigev_notify; // SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD
	void (*sigev_notify_function)(union sigval);
	pthread_attr_t *sigev_notify_attributes;
    };
    union sigval {
	int sival_int;
	void *sival_ptr;
    };

int timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
		   struct itimerspec *ovalue);
int timer_gettime (timer_t timerid, struct itimerspec *value);
int timer_getoverrun (timer_t timerid);
   struct timespec {
       time_t tv_sec;                /* Seconds */
       long   tv_nsec;               /* Nanoseconds */
   };

   struct itimerspec {
       struct timespec it_interval;  /* Timer interval */
       struct timespec it_value;     /* Initial expiration */
   };

Maxim Kartashev

Maxim Kartashev
Pragmatic, software engineer. Working for Altium Tasking on compilers and tools for embedded systems.