简体   繁体   English

Linux系统调用与C lib函数

[英]Linux system calls vs C lib functions

I have bit bit of confusion regarding these two so here are my questions; 我对这两者有些困惑,所以这是我的问题。

The Linux man-pages project lists all these functions: https://www.kernel.org/doc/man-pages/ Linux手册页项目列出了所有这些功能: https : //www.kernel.org/doc/man-pages/

Looking at recvfrom as an example, this function exists both as a Linux system call as well as a C library function. recvfrom为例,该函数既作为Linux系统调用又作为C库函数存在。 Their documentation seems different but they are both reachable using #include <sys/socket.h> . 他们的文档似乎有所不同,但是都可以使用#include <sys/socket.h> I don't understand their difference? 我不明白他们的区别吗?

I also thought systems calls are defined using hex values which can be implemented in assembly directly, their list is here: https://syscalls.kernelgrok.com/ 我还认为系统调用是使用可以直接在汇编中实现的十六进制值定义的,其列表在此处: https : //syscalls.kernelgrok.com/

However I cannot find recvfrom in the above link. 但是我在上面的链接中找不到recvfrom I'm a bit confused between Linux system calls vs C lib functions at this point! 在这一点上,我对Linux系统调用与C lib函数之间有些困惑!

Edit: To add to the questions, alot of functions are under (3) but not (2), ie clean . 编辑:要添加到问题,很多功能在(3)下,但不在(2)下,即clean Does this mean these are done by C runtime directly without relying on system calls and the underlying OS? 这是否意味着这些操作是直接由C运行时完成的,而不依赖于系统调用和底层OS?

exists both under the linux system call 在linux系统调用下都存在

The way userspace programs communicate with kernel is by using syscall function. 用户空间程序与内核进行通信的方式是使用syscall函数。 All syscall() does is push some number on specific registers and then execute a special interrupt instruction. syscall()所做的全部工作是在特定寄存器上压入一些数字,然后执行特殊的中断指令。 On the interrupt the execution is transferred to kernel, kernel then reads data from userspace using special registers. 在中断发生时,执行转移到内核,然后内核使用特殊的寄存器从用户空间读取数据。

Each syscall has a number and different arguments. 每个系统调用都有一个数字和不同的参数。 User space programs are expected to "find out" arguments for each syscall by for example inspecting the documentation. 用户空间程序应通过例如查看文档来为每个系统调用“查找”参数。

Linux system call is just a number, like __NR_recvfrom which is equal to 231 on x86-64 architecture. Linux系统调用只是一个数字,例如__NR_recvfrom ,在x86-64体系结构上等于231。

C Lib function C库功能

AC library function is a function implemented by the C library implementation. AC库功能是由C库实现实现的功能。 So, for example glibc implements recvfrom as a simple wrapper around syscall(__NR_recvfrom, ...) . 因此,例如glibc将recvfrom实现为syscall(__NR_recvfrom, ...)的简单包装。 This is C interface the library provides programmers to access kernel related functions. 该库是C接口,为程序员提供了访问内核相关功能的方法。 So C programmers wouldn't need to read the documentation for each syscall and have nice C interface to call the kernel. 因此,C程序员无需阅读每个系统调用的文档,也无需使用漂亮的C接口来调用内核。

However I cannot find recvfrom in the above link. 但是我在上面的链接中找不到recvfrom。

Don't use the link then. 那就不要使用链接。 At best inspect kernel sources under uapi directory. 最好检查uapi目录下的内核源。

First of all, functions listed in section (2) are functions . 首先,第(2)节中列出的函数functions They are different from functions in section (3) in that there is always a system call behind. 它们与第(3)节中的函数的不同之处在于,始终后面有系统调用。

Those function will usually do additional work to make them behave like POSIX functions (converting returned value to -1 and errno ), or to just make them usable ( clone syscall requires libc integration to be useful). 这些函数通常会做一些额外的工作,以使它们像POSIX函数一样工作(将返回值转换为-1errno ),或者只是使其变得可用( clone syscall要求使用libc集成才有用)。 Sometimes arguments are passed to a system call differently than function prototype suggests, for example they can be packed into a structure and pointer to that structure can be passed through a register. 有时参数传递给系统调用的方式与函数原型所建议的传递方式不同,例如,可以将参数打包到结构中,并且可以通过寄存器传递指向该结构的指针。

Sometimes a new syscall is added to fix some issues of the older syscall. 有时会添加一个新的系统调用,以解决旧系统调用的某些问题。 In this can a function can be implemented using a new syscall transparently (see mmap vs mmap2 , sys_select vs sys_old_select ). 在这种情况下,可以透明地使用新的syscall来实现功能(请参阅mmapmmap2sys_selectsys_old_select )。

As for recvfrom , socket-related functions are implemented by either their respective syscalls or by a legacy sys_socketcall . 至于recvfrom ,套接字相关的功能是通过它们各自的syscall或旧版sys_socketcall For example musl still has this code: 例如,musl仍然具有以下代码:

#ifdef SYS_socket
#define __socketcall(nm,a,b,c,d,e,f) syscall(SYS_##nm, a, b, c, d, e, f)
#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(SYS_##nm, a, b, c, d, e, f)
#else
#define __socketcall(nm,a,b,c,d,e,f) syscall(SYS_socketcall, __SC_##nm, \
    ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(SYS_socketcall, __SC_##nm, \
    ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
#endif

which tries to use appropriate syscall if available, backing off to socketcall otherwise. 如果可用,它将尝试使用适当的syscall,否则返回到socketcall

First, understand that that C functions and system calls are two completely different things . 首先,请了解C函数和系统调用是完全不同的两件事

System calls not wrapped in the C library must be called through the syscall function. 未包装在C库中的系统调用必须通过syscall函数syscall One example of such a call is gettid . 这样的调用的一个例子是gettid

To create a gettid system call wrapper with syscall , do this: 要使用syscall创建gettid系统调用包装器,请执行以下操作:

#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

pid_t gettid(void)
{
    pid_t tid = (pid_t)syscall(SYS_gettid);
    return tid;
}

Here's an excerpt from the NOTES section of the man-page, which explicitly states that this function is not defined within the C library: 以下是手册页的NOTES部分的节选,该节明确指出此函数未在C库中定义:

NOTES 笔记
Glibc does not provide a wrapper for this system call; Glibc不为此系统调用提供包装器; call it using syscall(2). 使用syscall(2)调用它。


recvfrom is a C library wrapper around a system call. recvfrom是围绕系统调用的C库包装器。
Everything in section (2) is a system call. 第(2)节中的所有内容都是系统调用。 Everything in section (3) is not. 第(3)节中的所有内容都不是。 Everything in section (3) (with a few notable exceptions, such as getumask ) has a definition in the C library. 第(3)节中的所有内容(有一些值得注意的例外,例如getumask )在C库中都有一个定义。 About half of everything in section (2) does not have a definition (or wrapper) within the C library (with the exception of functions mandated by POSIX, and some other extensions, which all do), as with gettid . gettid一样,第(2)节中几乎所有内容的一半都没有在C库中定义(或包装)(由POSIX强制执行的功能以及某些其他扩展都具有)。

When calling recvfrom in C, the C library calls the kernel to do the syscall. 在C语言中调用recvfrom时,C库将调用内核以进行syscall。

The syscall function is the function that puts the system call number in the %eax register and uses int $0x80 . syscall函数是将系统调用号码放入%eax寄存器并使用int $0x80的函数。

The reason you don't see recvfrom in https://syscalls.kernelgrok.com/ is because https://syscalls.kernelgrok.com/ is very, very incomplete. https://syscalls.kernelgrok.com/中看不到recvfrom的原因是因为https://syscalls.kernelgrok.com/非常不完整。

The reason there are many functions in (3) that you don't see in (2) is because many functions on (3) don't have a system call. (3)中没有在(2)中看到许多函数的原因是,(3)中的许多函数没有系统调用。 They may or may not rely on system calls, they just don't have a system call with that specific name that backs them. 他们可能会或可能不会依赖系统调用,只是他们没有使用支持它们的特定名称的系统调用。

Looking at recvfrom as an example, this function exists both as a Linux system call as well as a C library function. recvfrom为例,该函数既作为Linux系统调用又作为C库函数存在。

I was able to find 2 pages for recvfrom : 我能够找到2页的recvfrom

Often, the Linux page also tells how Linux version of the function differs from POSIX one. 通常,Linux页面还会告诉您该功能的Linux版本与POSIX版本有何不同。

They are different from functions in section (3) in that there is always a system call behind [section 2]. 它们与第(3)节中的函数的不同之处在于,[第2节]后面始终有一个系统调用。

Not necessarily. 不必要。 Section 2 is Linux-specific API for user-space applications. 第2节是针对用户空间应用程序的特定于Linux的API。 Linus Torvalds insists that user-space applications must never be broken because of Linux kernel API changes. Linus Torvalds坚称,绝不能因为Linux内核API的更改而破坏用户空间应用程序。 glibc or another library normally implement the functions, to maintain the stable user-space API and delegate to the kernel. glibc或其他库通常实现这些功能,以维护稳定的用户空间API并委托给内核。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM