Linux之vfork

vfork

vfrok用于创建一个新进程,而新进程的目的是为了exec一个新程序。vfork和fork的区别是vfork它不会将
父进程的地址空间复制一份到子进程。因为子进程会立即调用exec或exit,也就不会对这块地址读写了。
而在子进程调用exec之前,其在父进程的空间中运行。另外一个区别是vfork保证子进程先运行,父进程在
这段时间挂起,直到子进程调用了exec或exit,才会去调用父进程
 
vfork() differs from fork(2) in that the parent is suspended until  the
child  terminates (either normally, by calling _exit(2), or abnormally,
 after delivery of a fatal signal), or it makes  a  call  to  execve(2).
Until  that point, the child shares all memory with its parent, includ-
ing the stack.  The child must not return from the current function  or
call exit(3), but may call _exit(2)
vfork同父进程××共用××内存空间。vfork的代码执行的时候,父进程是停止的,
不然父子进程就会使用同样的内存空间,就会相互干扰。只有当子进程执行完毕退出时,
他会向父进程发送SIGCHILD信号告知父进程,父进程才会继续运行。但是如果子进程如果不
是通过这几种方式结束(by calling _exit(2), or abnormally,  after delivery of a fatal signal),
or it makes  a  call  toexecve(2).)就会从同父进程共用的代码中返回,也就是从main中返回,这时就会操作main的栈(因为父子的内存空间是共用的),
子进程可以很好的退出。但是当父进程也从main退出的时候,其栈上的内容,特别是返回地址被子进程返回的时候修改了。
因此从main返回后从栈中取出的返回地址是一个不可预测的地址,这时一般就会产生内存访问错误。
### Linux 中 `fork`、`vfork` 和 `clone` 系统调用的区别及应用场景 #### 一、基本概念与功能差异 - **`fork()`** 创建一个新进程,该进程几乎完全复制了父进程的状态。子进程中除了拥有独立的PID外,其他资源如内存映射、文件描述符等均被复制了一份新的副本[^1]。 - **`vfork()`** 类似于`fork()`, 不同之处在于它并不为子进程创建完整的地址空间拷贝;相反, 子进程会暂时借用并锁定父进程的部分地址空间直到子进程执行特定操作(比如exec系列函数),在此期间不允许父进程运行以防止数据竞争条件发生[^3]。 - **`clone()`** 提供更灵活的方式去创建轻量级进程或线程。通过传递不同的标志位给此系统调用来控制哪些资源应该共享而不是复制。例如可以指定仅共享某些部分而不必像传统意义上的父子关系那样全面克隆整个环境[^4]。 #### 二、内部机制对比 对于这三个系统调用而言,在底层实现上它们都会调用到共同的核心逻辑——即`do_fork()` 函数来进行实际创建工作: - 当`fork()` 被调用时,传入`do_fork()` 的参数使得所有需要有条件复制的资源都将被执行真正的复制动作; - 对应`vfork()` 来说,则设置了特殊的标记让其只做有限度的数据结构浅层复制,并且允许子进程直接访问父进程的一部分内存区域直至完成必要的任务切换回父进程继续工作之前; - 至于`clone()` ,则依据用户所提供的额外选项来自定义行为模式,从而满足更加多样化的需求场景下的应用开发需求。 ```c pid_t pid; // 使用 fork() pid = fork(); if (pid == 0){ // child process code here... } else { // parent process code here... } // 使用 vfork(), 注意这里的子进程不应该修改任何全局变量或堆上的对象 pid = vfork(); if(pid == 0){ execlp("/bin/ls", "ls", NULL); } else{ wait(NULL); /* Wait for the exec'd program to finish */ } // 使用 clone() int stack_size = 65536; void *stack = malloc(stack_size); pid = clone(child_func, stack + stack_size, SIGCHLD, arg); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值