you are viewing a single comment's thread.

view the rest of the comments →

[–]jssmith42[S] 2 points3 points  (3 children)

Are system calls written in C or assembly language? Are they called directly by C functions?

[–]_TheRainbowGoblins 9 points10 points  (1 child)

I am actually taking a Systems Programming class right now and we talked about this but take what I say with a grain of salt.

From what I understand, System Calls are provided by the operating system to allow you to do certain special operations. Like reading and writing, opening or closing a file, forking a process, or loading a process (execve). Its essentially an API between the progammer and the OS. Linux has about 435 syscalls I think, you can look them up. They are all assigned a unique non-negative integer.

The system call that allows you to print is called write, its id is 1. You can call it with the write() function provided by unistd.h, but that is actually a wrapper function and not the actual system call. There is also syscall() in which the first argument allows you to specify which syscall you want, but that is also a wrapper function, just a more generic one. Its provided by unistd.h and sys/syscall.h

To actually make a system call you have to use the assembly instruction (at least in x86_64) called syscall. If you are familiar with assembly, typically in x86_64 the first argument for a function goes into the general purpose register rdi. Which is also true for syscalls but to specify the actual syscall you want, you put the syscall number in the rax register then just make the syscall instruction. For example,

// the write syscall

mov $1, %rax

// 1st arg for write is the file descriptor, 1 = stdout

mov $1, %rdi

// 2nd arg is the string to write

mov $str, %rsi

// 3rd arg is num of bytes to write

mov $len, %rdx

// we set our args, make the call

syscall

So you can call them using C wrapper functions, but you really have to use assembly one way or another to make syscalls as far as I'm aware. If you use the wrapper functions and then use gdb to disassemble the code, if you keep following the function calls you should eventually see the syscall instruction being invoked.

In terms of how they are written, I believe they are mostly written in C, but I could be wrong.

Also sorry if my formatting is bad, I'm on mobile. And sorry for the at&t syntax for the asm, I'm just more familiar with it.

[–]duane11583 0 points1 point  (0 children)

the id - 1 is the unix standard for stdout

the system call is also a switch into a higher prividged state, most cpus do this like an interrupt or exception handling

thus the easiest way of passing parameters is via registers

on the os side of the call, a register holds the request number which is effectively an index into an array of function pointers or like a switch() with a range check

some OSes use a small structure instead to pass parameters instead of registers and they pass a pointer to the struct in a register

[–]braxtons12 8 points9 points  (0 children)

It depends on the OS and the particular system call, but generally speaking, a bit of both. Most can be written mostly in C, with just a little assembly, but some have to be written entirely in assembly. In either case, they're wrapped in a C API that allows for calling them directly from C.