On Linux, there's typically both an open(3) and an open(2). The former is implemented by glibc and calls the latter which is implemented by the kernel.
So an app calls the open() function. This results in an unresolved symbol which the run-time linker matches up with the open() exported by glibc. glibc then does the open() syscall.