是linux fork不安全

我正在阅读这篇文章

它说,叉子创build自己的副本, fork人也这样说

。 父级的整个虚拟地址空间被复制到子级中

这是否意味着subprocess可以读取我所有的进程内存状态?

subprocess可以转储整个父内存状态,可以分析它以提取父variables及其值。

但文章还说,两个进程不能准备好对方的数据。 所以我很困惑?

是的,子进程可以在fork(2)后面读取所有父进程状态的原始副本 (但在写入时,只影响其自己的地址空间) 。 但是,大多数情况下,孩子最终会使用execve(2)来启动一个新的程序,并且将“清除”并替换原始父地址空间的副本(通过新的地址空间)。 请注意, execve和mmap(2) (另请参阅shm_overview(7) …中的共享内存 )是更改某个进程的 虚拟内存中的地址空间 (以及内核如何处理页面错误 )的常见方法。

内核使用(和设置MMU ) 写机器上的懒写来使子地址空间成为父节点的副本,所以在实践中fork是相当有效的。

另请阅读proc(5) ,然后输入以下命令:

 cat /proc/self/maps cat /proc/$$/maps sudo cat /proc/1/maps 

并了解正在发生的事情

请阅读fork上的wikipage,以及高级Linux编程手册。

没有不安全感,因为如果孩子正在改变一些数据(例如变量,堆或堆栈位置等),它不会影响父进程。

如果执行fork的程序在某个虚拟内存位置保留一些密码,那么只要子进程正在执行相同的程序,子进程就可以读取该位置。 一旦孩子做了一个成功的execve (这是常见的情况,以及任何shell正在做什么),以前的地址空间已经不存在了,并替换为一个新的,在该exec -ed程序的ELF可执行文件中描述的。

Unix模式中没有“谎言”或“不安全”。 但与其他几个操作系统相反,Unix和POSIX有两个独立的系统调用来创建一个新的进程( fork )并执行一个新的程序( execve )。 其他系统可能会有一些混合两种能力的生成操作。 posix_spawn通常由forkexecve (以及system(3)和popen(3) ,也使用waitpid(2) & /bin/sh ….)的混合来实现。

这种Unix方法(分离forkexecve )的优点是,在fork和child的execve之前,你可以做很多有用的事情(例如关闭无用的文件描述符,…)。 操作系统不分离这两个功能可能需要有一个相当复杂的产卵原语。

在某些情况下, fork 不会execve遵循。 一些MPI的实现可能会这样做,你也可以这样做。 但是你知道你可以通过自己的副本阅读所有父母的地址空间 – 所以你觉得不安全感正在成为一个有用的功能 。 在过去,你有过时的vfork阻止父母。 今天不需要使用它; 实际上, fork通常是通过克隆(2)来实现的,你不应该直接在实践中使用它(参见futex(7) …),而只是通过POSIX pthreads 。 但是把fork当作你的过程的魔法克隆者可能会有帮助。

编码时(甚至在C)不要忘记测试forkexecve失败。 看到错误(3)

PS。 fork系统调用和多重性理念一样难以理解。 两者都是“分时”的!

当你调用fork() ,新进程将获得父进程内存副本 (即变量,文件描述符等)。

这与所有线程共享相同内存空间的线程相反,即在一个线程中修改的变量将在所有其他线程中获得新值。

所以,如果分叉之后父进程修改了内存,那么子进程将看不到这个改变 – 因为内存已被复制,子进程的内存不会被修改。