问题描述
int filedesc = open("foo.txt",O_RDONLY);
filedesc
是用户进程中的变量,当开始执行open
时,cpu获取上下文切换并运行内核进程,如何将open
的返回值传递给{{ 1}}?
此外,与
相比filedesc
借助缓冲,使用FILE *file = fopen("foo.txt","r");
的 read / file速度要快得多,但是在后台调用fopen
的情况下,我想知道在这种情况下open
是否仍然一个接一个地检索字节吗?如果是这样,因为open
缓冲区处于用户进程中,并且在第一个问题中来回传递系统调用返回值的情况下,每个字节都会有上下文切换开销,它为什么运行得更快?预先感谢!
解决方法
“由于缓冲,打开速度更快[然后fopen
],但在后台却将其称为打开...”
通常,根据定义,如果function1()
实现包括调用function2()
,然后直接调用function2()
,并且如果使用与function1()
调用时相同的选项集,则将始终有一个执行时间更短。如果您看到fopen()
和open()
的相反情况,则表明直接调用open()
时使用的选项集必须与在{{1 }}。但是内部fopen()
的实现具有相同数量的参数do_sys_open()
,因此出于这个原因,速度差是不可能的。您应该质疑基准测试技术。
关于如何将返回值返回给用户...
Linux系统调用是使用SYSCALL_DEFINEn的变体定义的。 open()
的以下example implementation对此进行了说明,并显示了在对函数open()
的封装中,其中一个参数在do_sys_open()
和{该功能,使其能够跟踪发起呼叫的用户:
const char __user *
,
我想你在这里有点困惑。当您说fopen()
更快时,您实际上的意思是fread()
和fwrite()
比read()
和write()
快。对于许多实现而言,这都是正确的,因为C标准库在用户空间中使用缓冲,而大多数POSIX实现在用户空间中不使用缓冲。但是,他们可能会在内核空间中使用缓冲。
假设您正在复制一个1kb的文件。如果一次执行一个字节,使用read()
从文件中获取一个字节,然后使用write()
将其复制到另一个字节中,则最终将调用相应的系统调用1024次。每次都有从用户空间到内核空间的上下文切换。另一方面,如果您使用内部使用512字节缓冲区的C库实现,那么即使您成千上万次调用fread
和fwrite
,它实际上也仅转换为两个系统调用的时间。因此,与直接使用read/write()
相比,它似乎要快得多。
但是,除了在同一时间复制一个字节之外,您还可以在应用程序中使用足够大的缓冲区,并尽可能少地调用read/write
来获得与系统调用相同或更好的性能。直。换句话说,并不是标准库API比系统调用快(这是不可能的,因为库是在内部调用系统调用),而是使用更大的缓冲区来调用read/write
系统调用效率更高,因为上下文切换开销和标准库已经考虑到这一点。