系统调用返回值如何传递回用户进程?

问题描述

假设我们有一个正在运行的核心cpu

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库实现,那么即使您成千上万次调用freadfwrite,它实际上也仅转换为两个系统调用的时间。因此,与直接使用read/write()相比,它似乎要快得多。

但是,除了在同一时间复制一个字节之外,您还可以在应用程序中使用足够大的缓冲区,并尽可能少地调用read/write来获得与系统调用相同或更好的性能。直。换句话说,并不是标准库API比系统调用快(这是不可能的,因为库是在内部调用系统调用),而是使用更大的缓冲区来调用read/write系统调用效率更高,因为上下文切换开销和标准库已经考虑到这一点。