Gan*_*pur 6 c linux system-calls
对于以下代码段,
int n;
char buf[100];
int fd = open ("/etc/passwd", O_RDONLY);
n = read ( fd, buf, 100);
Run Code Online (Sandbox Code Playgroud)
编译器如何知道read是系统调用而不是任何库函数?
它如何检索系统调用号(__NR_read)?
pax*_*blo 13
我非常怀疑编译器知道它是一个系统调用.它更可能出现open在某个库中,并且库中的代码调用相关的内核接口.
简单程序的程序集输出:
#include <stdio.h>
int main (void) {
int fd = open("xyz");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是(删除不相关的位):
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.
Run Code Online (Sandbox Code Playgroud)
你会注意到的第一件事就是打电话给open.换句话说,它是一个功能.没有int 80或sysenter看不见,这是用于正确系统调用的机制(无论如何在我的平台上 - YMMV).
libc中的包装函数是完成访问系统调用接口的实际工作的地方.
维基百科关于系统调用的摘录:
通常,系统提供位于正常程序和操作系统之间的库,通常是C库(libc)的实现,例如glibc.该库存在于OS和应用程序之间,并提高了可移植性.
在基于exokernel的系统上,该库作为中介尤其重要.在exokernel上,库将用户应用程序与极低级别的内核API隔离开来,并提供抽象和资源管理.
术语"系统调用"和"系统调用"通常被错误地用于引用C标准库函数,特别是那些充当相同系统调用的包装器的函数.对库函数本身的调用不会导致切换到内核模式(如果执行尚未处于内核模式)并且通常是正常的子例程调用(即,在某些ISA中使用"CALL"汇编指令).实际的系统调用确实将控制转移到内核(并且比抽象它的库调用更依赖于实现).例如,
fork并且execve是GLIBC功能,在依次调用fork和execve系统调用.
并且,经过一些搜索后,该__open函数可以在io/open.c文件中的glibc 2.9中找到,并且weakref编辑为open.如果你执行:
nm /usr/lib/libc.a | egrep 'W __open$|W open$'
Run Code Online (Sandbox Code Playgroud)
你可以在那里看到它们:
00000000 W __open
00000000 W open
Run Code Online (Sandbox Code Playgroud)
就编译器而言,read是一个库调用.碰巧的是,libc实现定义了read以生成具有正确数字的软件中断.