我在一篇文章中读到,创建进程和线程的底层系统调用实际上是相同的,因此创建进程的成本并不比创建线程高。
- 首先,我想知道创建进程/线程的系统调用是什么(可能需要示例代码或链接)?
- 其次,作者是否正确地认为创建进程而不是线程不费力?
编辑:
引用文章:
在Linux上,用进程替换pthread的成本意外地低,因为两者都使用相同的底层系统调用。
我在一篇文章中读到,创建进程和线程的底层系统调用实际上是相同的,因此创建进程的成本并不比创建线程高。
编辑:
引用文章:
在Linux上,用进程替换pthread的成本意外地低,因为两者都使用相同的底层系统调用。
进程通常是用fork
创建的,线程(轻量级进程)现在通常使用clone
创建。但是,有时也存在1:N线程模型,它们两者都不使用。
无论是fork
还是clone
在内部映射到相同的内核函数do_fork
。这个函数可以创建一个共享旧地址空间的轻量级进程,或者一个单独的进程(以及许多其他选项),具体取决于您向其提供的标志。 clone
系统调用更或多或少直接转发该内核函数(并由更高级别的线程库使用),而fork
则将do_fork
包装到50年前传统Unix功能的功能中。
重要的区别是fork
保证复制整个、单独的地址空间。正如Basil正确指出的那样,现在使用copy-on-write来完成,因此不像人们想象的那么昂贵。
当您创建线程时,它仅重用原始地址空间和相同的内存。
但是,人们不应该认为在类unix系统上创建进程通常是"轻量级"的,因为有了复制写入技术。它比Windows下的情况稍微轻一些,但它不是完全免费的。
一个原因是虽然实际页面没有复制,但新进程仍然需要页面表的副本。对于使用大量内存的进程,这可能是几千字节到几兆字节的内存。
另一个原因是尽管复制写入技术是看不见的且是一个聪明的优化,但它不是免费的,也不能做魔术。当数据被任一进程修改时(这不可避免地会发生),受影响的页面会出现故障。
Redis是一个很好的例子,您可以在其中看到fork
远非轻量级(它使用fork
进行后台保存)。
do_fork
。一般情况下,您可能也不想使用 clone
(建议使用在其上构建的 pthreads 库)。无论如何,如果您确实想要使用 clone
,可以查看文档这里。另一方面, fork
是您真正想使用的东西,文档位于同一网站上。 - Damonfork
和pthread_create
的源代码。但我找不到任何对do_fork
的调用。 - atoMerz创建线程的底层系统调用是clone(2)(它是特定于Linux的)。顺便说一下,Linux系统调用列表在syscalls(2)上,您可以使用strace(1)命令了解某些进程或命令执行的系统调用。进程通常使用fork(2)(或vfork(2),这在现今不太有用)。但是,您可以(某些C标准库可能会这样做)使用某种特殊形式的clone
来创建它们。我想内核正在共享一些代码来实现clone
、fork
等功能(因为一些功能,例如虚拟地址空间的管理是共同的)。
事实上,在大多数Unix系统上,进程创建(以及线程创建)通常非常快(因为它们使用写时复制机制来处理虚拟内存),通常只需几毫秒的时间。但是您可能会遇到病态情况(例如抖动),这会使得创建进程或线程需要更长的时间。
由于大多数Linux上的C标准库实现都是自由软件,因此您可以研究您系统上的源代码(通常使用GNU glibc,但有时也会使用musl-libc或其他库)。
fork
可以使用 clone
实现(但前者比后者早了十几年)。 - Basile Starynkevitch