为什么x86和x86_64中的Linux系统呼叫号码不同?


35

我知道系统调用接口是在较低级别上实现的,因此依赖于体系结构/平台,而不是“通用”代码。

但是,我不清楚为什么在32位x86内核的Linux中系统调用的编号在相似的体系结构Linux 64位x86_64中不保持相同的原因?做出此决定的动机/原因是什么?

我的第一个猜测是,后台原因是使32位应用程序在x86_64系统上可运行,因此通过合理地偏移系统调用号,系统将知道用户空间是32位还是64位分别。但是事实并非如此。至少在我看来,read()是x86_64中的系统调用号0,无法与这种想法保持一致。

另一个猜测是,更改系统电话号码可能具有安全性/强化背景,而我无法确定自己的身份。

由于对实现与体系结构相关的代码部分所面临的挑战一无所知,我仍然想知道如何在似乎没有必要的情况下更改系统调用号(因为即使一个16位寄存器也将存储比当前约346个数字大得多的数字,以代表全部)调用),将有助于实现除破坏兼容性以外的任何功能(尽管通过库libc使用系统调用可以缓解这种情况)。


3
我认为您在问错问题。正确的问题是为什么要保持它们相同:回答兼容性。因此,如果x86和x86_64不兼容,则没有力量阻止它们更改。现在,过去20年中所有想要改变的力量将占主导地位(我们有机会改变它们)。[请注意,这仅是意见,并不基于新系统设计人员的内心。]
ctrl-alt-delor

Answers:


34

至于特定编号背后的原因,该编号与任何其他体系结构均不匹配[除了“ x32”实际上只是x86_64体系结构的一部分]:在Linux内核中对x86_64支持的早期,由于存在严重的向后兼容性限制,因此所有系统调用都已重新编号,以在高速缓存行使用级别对其进行优化

我对内核开发的了解还不够,无法知道这些选择的具体依据,但是显然,在选择背后有一些逻辑,那就是用这些特定数字对所有内容重新编号,而不是简单地从现有体系结构中复制列表并删除未使用的列表。看起来顺序可能取决于调用它们的频率-例如,读/写/打开/关闭位于最前面。退出和派生似乎是“基本的”,但每个进程仅被调用一次。

可能还会在同一缓存行中保留共同使用的系统调用(这些值只是整数,但是内核中有一个表,每个表都有函数指针,所以每组8个系统调用占用该表的64字节缓存行)


1
fork may seem "fundamental", but [...] called only once per process.嗯什么 我了解您可能希望一次致电出口,但您可能会在一次fork()通话的父母和孩子中分叉
cat

5
@cat,如果您将fork视为子进程(即,将其视为进程创建调用)而不是父进程,则将其视为父进程,则Random832的语句是正确的。
icarus

4
@cat好,您可以调用fork()两次或三遍,也许再调用几遍。但是您可能会调用read()数百万甚至数十亿次。
迈克尔·汉普顿

1
是的,这就是我的意思。叉的呼叫的数量和在系统的生命周期过程的数量将是相同的,忽略象初始化细节,克隆[其可以创建进程或线程]等
Random832

15

看到以下问题的答案: “为什么amd64 linux中的系统调用号不同?” 在堆栈溢出。

总结一下:为了兼容,系统调用列表是稳定的并且只能增长。当x86 64体系结构出现时,ABI(参数传递,返回值)有所不同,因此内核开发人员借此机会带来了期待已久的更改。


很酷,我的猜测是正确的。
ctrl-alt-delor

2
您链接到的其他答案是推测性的:它表示“ Linux伙计们最有可能决定...”(着重强调)。我想如果您的回答提供一些迹象表明它显然是基于推测而不是证据,那将会有所帮助。顺便说一句,在链接的答案下发布的更新评论提供了证据,证明真正的原因不是对垃圾的一般清理(正如该答案所推测的那样),而是专门关于“缓存行用法”,如此处其他答案所述
DW

-3

简而言之,因为有人认为“ N+1做这些事的不相容的方法总比做的更好N”。对于历史拱门,通常选择syscall编号以匹配某些旧有的专有unix。但是对于x86_64,内核开发人员可以自由选择他们喜欢的任何编号。他们没有选择简单的选择并重复使用现有的编号,而是选择了发明新的标准。然后,他们又为aarch64和其他一些对象再次使用了它。这是Linux内核开发中经常重复使用的模式。


3
更改不是免费的。有可靠的技术原因。如果不是为了向后兼容,那么对现有体系结构也将进行类似的更改。
约尔格W¯¯米塔格

编号上的差异是100%免费的。任何特定的编号都没有技术优势。
R.,

2
正如该其他答案所解释的那样,系统调用被分组,以便共同使用的系统调用在系统调用表中共享相同的缓存行。选择系统调用,使其成为该表的简单索引。从理论上讲,我们可以使用一个间接层将syscall在syscall表中的位置与syscall编号分离,但这可能会吞噬我们将热syscall放在同一缓存行中而获得的部分性能提升。
约尔格W¯¯米塔格

@JörgWMittag:这显然是过早的优化,而不是可衡量的改进。只需查看syscall花费了多少个周期以及它们驱逐了多少个缓存行。从表的顺序中最多保存一条缓存行不会有什么不同。
R.,

2
@R ..“我选择了流行的DBMS和一些网络和桌面应用程序的strace输出的tpcc内核概要分析信息功能的编号。” 听起来确实有些测量。但是,作者没有提供任何数字或没有对方法进行充分解释。
user45891
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.