类UNIX操作系统中的系统调用是可重入的(即可以并行执行多个系统调用)。在C / C ++ 11的关系之前,是否有任何系统调用的排序约束?
例如,让我们考虑以下带有3个线程的程序(伪代码):
// thread 1
store x 1
store y 2
// thread 2
store y 1
store x 2
// thread 3
Thread.join(1 and 2)
wait((load x) == 1 && (load y) == 1)
此处,假设x
和y
是共享位置,并且所有load
和store
都具有宽松排序。 (注意:对于放松的原子访问,比赛不被视为错误;它们在C / C ++ 11语义的意义上是故意的。)此程序可能会终止,因为(1)编译器可能会重新排序{ {1}}和store x 1
,然后(2)执行store y 2
,store y 2
,store y 1
,然后执行store x 2
,以便(3)线程3可以同时阅读store x 1
和x = 1
。
我想知道以下程序是否也可以终止。在这里,一些系统调用y = 1
& {1}已插入主题1& 2,分别:
syscall1()
程序似乎无法终止。但是,在没有调用系统调用的排序约束的情况下,我认为这个程序可能会终止。这就是原因。假设syscall2()
和// thread 1
store x 1
syscall1()
store y 2
// thread 2
store y 1
syscall2()
store x 2
// thread 3
Thread.join(1 and 2)
wait((load x) == 1 && (load y) == 1)
未序列化,可以并行运行。然后编译器在完全了解syscall1()
和syscall2()
的语义的情况下,仍然可以重新排序syscall1()
& syscall2()
和store x 1
。
所以我想询问是否存在由不同线程调用的系统调用的任何排序约束。如果可能的话,我想知道这类问题的权威来源。
答案 0 :(得分:1)
从用户土地上的应用程序的角度来看,system call(syscalls(2) ...中列出的那些)是基本操作。
每个系统调用(按照定义)通过一些单个 machine code指令(SYSENTER
,SYSCALL
,INT
调用内核。 ..);细节取决于处理器(其instruction set)和ABI。 kernel开展业务(处理系统调用 - 可能成功或失败),但您的用户程序只能看到一个基本步骤。有时这一步骤(在内核控制期间)可以持续长时间(例如几分钟或几小时)。
因此user land中的程序在低级虚拟机中运行,由处理器的user mode计算机指令提供,并由单个虚拟"系统调用指令(能够执行内核实现的任何系统调用)。
这并不是因为竞争条件而禁止你的程序出错。