A very interesting video that explains how the operating system can maintain control over user processes, regardless of what they do, how system calls work, and other concepts important to systems programming.
Fun fact, you can easily see what syscalls zig is doing! For example:
A typical socket creation:
const socket: std.posix.socket_t = try std.posix.socket(
std.posix.AF.PACKET,
std.posix.SOCK.RAW,
std.mem.nativeToBig(u32, ETH_P_ETHERCAT),
);
Calls (on linux):
pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
if (native_arch == .x86) {
return socketcall(SC.socket, &[3]usize{ domain, socket_type, protocol });
}
return syscall3(.socket, domain, socket_type, protocol);
}
Calls:
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
@setRuntimeSafety(false);
var buf: [2]usize = .{ @intFromEnum(number), undefined };
return asm volatile (
\\ str r7, [%[tmp], #4]
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize),
: [tmp] "{r3}" (&buf),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3),
: "memory"
);
}
That’s a system call!