Chapter 3 - System Calls
Chapter 3 - System Calls
System Calls
- Will always switch to Kernel mode
- Syscall number is fixed but user identify it by syscall func name.
How sys call works
- When userspace programs call syscall, then they store a number corresponsing to syscall on a register
%eax - The wrapper that has this
movcommand to register will also include atrapcalled0x80. In most newer architecturesysenteris used to enter kernel mode. - When this trap is encountered, CPU will start the
system_call()subroutine located inarch/i386/entry.Ssee.- this saves the register value to kernel stack
- checks the validity of syscall and executes it
- returns the value to program stack and switches to user mode
sys_call_tablehas all the list of system calls and its numbers.- for example -
sys_execvesyscall has number 11 and hence insys_call_table11th entry store the address of routine forsys_execvehandler. - use
straceto trace syscalls in a program.
library functions
- wrappers around syscall.
- Most common Linux is implemenetd in GNU C
- glibc version is determined from
/lib/libc.so.6 - one can also perform list dynamic list dependency like
ldd myprog | grep libcto check the version of libc
1
2
3
#include <gnu/libc-version.h>
const char *gnu_get_libc_version(void);
One can also call gnu_get_libc_version to get this.
#include <stdio.h>
#include <gnu/libc-version.h>
#include <errno.h>
int main() {
const char* version_no = gnu_get_libc_version();
if !(version_no) {
fprintf(stderr, "Error: Failed to retrieve glibc version\n");
return 1;
}
printf("version number :- %s\n", version_no);
return 0;
}
and output
1
2
Anurag252 ➜ /workspaces/codespaces-blank $ gcc main.c ; ./a.out
version number :- 2.39
error handling from syscall and library functions
- a few prgms never fail like
getpidandexitand their return need not be checked- system call failures set
errno perrorprints an error message pointed bymsgarguement and thenerrnoerrorstrerrorreturns error corresponsing toerrono.
- system call failures set
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main() {
ssize_t read_bytes = open("some/file", 1);
if (read_bytes == -1) {
perror("some error occured:- ");
printf("%s\n", strerror(errno));
return 1;
}
return 0;
}
- std lib function
- some return errno, some do not set errno but return an int, other do not do both
1
atoi(), atol(), and strtol()
- some return errno, some do not set errno but return an int, other do not do both
feature flags
- one can define feature flags like this
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main() {
if (MY_FEATURE) {
printf("hello\n");
return 0;
} else {
printf("bye\n");
return 1;
}
}
to test
1
gcc -D MY_FEATURE=0 main.c ; ./a.out
- there are pre-defined FFs which enable and disable multiple certain functionality and specially platform related code
- _POSIX_SOURCE
- _POSIX_C_SOURCE
- _XOPEN_SOURCE
system data type
- there are some pre-defined type
sszie_tfromopenwhich is int but to capture platform related specifics, they are system defined - generally have
_tat the end and it appears astypedef int pid_t; - most available in
<sys/types.h>
Exercise
1
2
3
4
5
man 2 reboot
This system call fails (with the error EINVAL) unless magic equals LINUX_REBOOT_MAGIC1 (that is, 0xfee1dead) and magic2 equals LINUX_RE‐
BOOT_MAGIC2 (that is, 0x28121969). However, since Linux 2.1.17 also LINUX_REBOOT_MAGIC2A (that is, 0x05121996) and since Linux 2.1.97 also
LINUX_REBOOT_MAGIC2B (that is, 0x16041998) and since Linux 2.5.71 also LINUX_REBOOT_MAGIC2C (that is, 0x20112000) are permitted as values for
magic2. (The hexadecimal values of these constants are meaningful.)
These hexadecimals are birrthdates 0x28121969 - 28.12.1969 and so on
This post is licensed under CC BY 4.0 by the author.