I very much doubt that the compiler knows it's a system call. It's far more likely that open
is in a library somewhere and the code within the library calls the relevant kernel interface.
The assembly output from the simple program:
#include <stdio.h>
int main (void) {
int fd = open("xyz");
return 0;
}
is (irrelevant bits removed):
main:
pushl %ebp ; stack frame setup.
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl $.LC0, (%esp) ; Store file name address.
call open ; call the library function.
movl %eax, 28(%esp) ; save returned file descriptor.
movl $0, %eax ; return 0 error code.
leave ; stack frame teardown.
ret
.LC0:
.string "xyz" ; file name to open.
The first thing you'll notice is that there's a call to open
. In other words, it's a function. There's not an int 80
or sysenter
in sight, which is the mechanism used for proper system calls (on my platform anyway - YMMV).
The wrapper functions in libc are where the actual work of accessing the system call interface is done.
An excerpt from Wikipedia on system calls:
Generally, systems provide a library that sits between normal programs and the operating system, usually an implementation of the C library (libc), such as glibc. This library exists between the OS and the application, and increases portability.
On exokernel based systems, the library is especially important as an intermediary. On exokernels, libraries shield user applications from the very low level kernel API, and provide abstractions and resource management.
The terms "system call" and "syscall" are often incorrectly used to refer to C standard library functions, particularly those that act as a wrapper to corresponding system calls with the same name. The call to the library function itself does not cause a switch to kernel mode (if the execution was not already in kernel mode) and is usually a normal subroutine call (i.e., using a "CALL" assembly instruction in some ISAs). The actual system call does transfer control to the kernel (and is more implementation-dependent than the library call abstracting it). For example, fork
and execve
are GLIBC functions that in turn call the fork
and execve
system-calls.
And, after a bit of searching, the __open
function is found in glibc 2.9 in the io/open.c
file, and weakref
'ed to open
. If you execute:
nm /usr/lib/libc.a | egrep 'W __open$|W open$'
you can see them in there:
00000000 W __open
00000000 W open