在Linux中,每一个新的进程都是透过一种称为父进程克隆的机制产生的。
-
当一个子进程刚刚被创建出来,它的虚拟内存空间中的信息是与其父进程一模一样的,这意味着它们的代码段和数据段是共享的。 -
子进程可以通过调用exec系列的函数来加载一个全新程序的信息,从而更新其自身的虚拟内存空间内容。
2.fork函数原理
2.1 fork函数原型
pid_t fork(void);
功能:创建一个新的进程。
参数:
无。
返回值:
fork函数调用一次返回两次。
-
父进程:返回子进程PID。
-
子进程:返回0。
-
失败:返回-1。
2.2 fork函数实现原理
2.3 父子进程虚拟地址空间(mm_struct)之间的关系
-
父子进程各自拥有自己独立的虚拟地址空间。 -
父子进程共享代码段(只读)。 -
采用写时拷贝(copy-on-write)技术创建子进程虚拟地址空间。
2.4 写时拷贝(copy-on-write)技术
传统fork函数缺点:
-
复制子进程虚拟地址空间时,存在大量拷贝,效率很低。 -
子进程立马需要执行execv函数替换虚拟地址空间内容,导致上一步复制子进程虚拟地址空间变得多余。
什么是写时拷贝?
写时拷贝是指父进程在创建子进程时,只创建虚拟地址空间,不为子进程分配实际的内存,父进程和子进程之间共享相同的物理内存页面。
当父进程或者子进程对虚拟地址空间对应的内存进行修改时才会分配实际内存。
写时拷贝技术优点:
-
节省内存开销。 -
提高创建进程效率。
拷贝前
拷贝后
2.5 父子进程如何共享文件(files_struct)
FD_CLOSEXEC文件标志?
子进程和父进程共享文件是一种不安全的行为,如果子进程调用exec家族函数,子进程的虚拟机制空间被新的程序替换,如果子进程还保留父进程的文件描述符表,后果很严重。
文件设置FD_CLOSEXEC文件标志后,子进程调用exec家族函数,该文件会被关闭。
如何设置FD_CLOSEXEC文件标志?
-
方法1:open函数带上O_CLOSEXEC标志。
如:open(“file”, O_RDWR | O_CREAT | O_TRUNC | O_CLOSEXEC, 0644 );
-
方法2:fcntl函数F_SETFD操作设置。
3.vfork函数原理
3.1 vfork函数原型
pid_t vfork(void);
功能:fork函数创建一个新的子进程,该子进程与父进程共享相同的地址空间。
参数:
无。
返回值:
vfork函数调用一次返回两次。
-
父进程:返回子进程PID。 -
子进程:返回0。 -
失败:返回-1。
3.2 vfork和fork函数区别?
-
vfork函数创建子进程和父进程共享地址空间。 -
使用vfork函数创建的子进程则会暂停父进程的执行,直到子进程调用exec()或者_exit()函数退出或替换自己的地址空间。
不推荐使用vfork函数!!!
vfork函数由于子进程和父进程共享地址空间,vfork比传统fork函数效率高。随着写时复制技术出现,这个优势已经不存在了。
vfork存在不安全的行为,所以不推荐使用vfork函数。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !