fork()函数,fork()子进程父进程的比较总结,fork()与vfork()的比较总结

本文介绍了fork()和vfork()函数在进程创建中的作用,阐述了两者在创建子进程时的区别,包括执行顺序、地址空间共享以及资源复制等方面。fork()创建的子进程拥有父进程的副本,不共享数据;而vfork()则共享地址空间,子进程先运行,直至调用exec()或exit()。不当使用vfork()可能导致死锁或栈错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程创建fork()

fork()函数以父进程为蓝本复制一个进程,其ID号与父进程ID号不同,内存等与父进程不同,其他与父进程同享,只有在父进程或者子进程进行了修改后,才重新生成一份。

成功时,fork返回是进程ID,失败返回-1;

#include<sys/types.h>

#include<unistd.h>

pid_t fork(void)

for k()的特点是执行一次,返回两次。在父进程和子进程中返回的是不同的值,父进程返回的是子进程的ID号,而在子进程中返回0。fork函数创建一个新的进程,并从内核中为此进程得到一个新的可用进程ID,之后为这个新进程分配进程空间,并将父进程的进程空间中的内容复制到子进程的进程空间中,包括父进程的数据段+堆栈段,并与其父进程共享代码段。

在Linux中,通常把调用fork系统调用的进程称为父进程,把新产生的进程称为子进程。

fork()子父进程变量共享情况

子进程会拷贝父进程的所有资源,变量

注意:子进程拷贝了父进程数据空间、堆、栈等资源的副本,

父子进程间不共享这些存储空间,共享的空间只有代码段,

子进程修改一个全局变量,父进程的这个全局变量不会改变,因为是一个副本。

子进程从父进程拷贝的内容主要有以下:

用户号UIDS和用户组号GIDS

环境Environment

堆栈

共享内存

打开文件的描述符

执行时关闭标志

信号控制设定

进程组号

当前工作目录

根目录

文件方式创建屏蔽字

资源限制

控制终端

子进程独有

进程号PID

不同的父进程号

自己的文件描述符和目录流的拷贝

子进程不继承父进程的进程正文,数据和其他锁定内存

不继承异步输入和输出

父进程和子进程拥有独立的地址空间和PID参数

案例:

执行结果:

Vfork()函数:

Vfork()函数和fork()函数一样都是在已有进程中创建一个新的进程,但他们创建的子进程是有区别的。

所需头文件:

#include<sys/types.h>

#include<unistd.h>

pid_t  vfork(void);

参数:无

返回值:

成功:子进程中返回0,父进程中返回子进程ID。pid_t,为无符号整型。

失败返回-1

fork() 与 vfock() 都是创建一个进程,那它们有什么区别呢?

  1. fork():父子进程的执行次序不确定

vfork ():保证子进程先运行,在它调用exec(进程替换)或exit(退出进程)之后父进程才可能被调度运行。

2)fork():子进程拷贝父进程的地址空间,子进程是父进程的一个复制品

   vfork ():子进程共享父进程的地址空间(准确来说,在调用exec(进程替换)或exit(退出进程)之前与父进程数据是共享的)

 

案例:

/*

通过 vfork() 创建的子进程会执行完后,才到父进程执行

子进程共享父进程的地址空间

*/

执行结果:可看到vfork创建的父子进程的空间地址是一样的,即共享一份地址空间。

https://i-blog.csdnimg.cn/blog_migrate/9fe5959987329a6fc09246f052da79c1.png

案例:

/*

vfork()保证子进程先运行,在它调用exec(进程替换)或exit(退出进程)之后父进程才可能被调度运行

如果子进程没有调用execexit,程序则会导致死锁,程序是有问题的程序,没有意义。

*/

结果如下:

如果子进程使用return返回也会问题

 

 

输出结果如下:

原因分析:从上面我们知道,结束子进程的调用是exit()而不是return,如果你在vfork中return了,那么,这就意味着main()函数return 了,而因为函数栈父子进程共享,所以整个程序栈就出问题了。

若子进程中return,那么基本是下面的过程:

  1. 子进程的main()函数return了,于是程序的函数栈发生了变化。
  2. 而main()函数return后,通常会调用exit()或相似的函数(如:_exit(),exitgroup())
  3. 这时,父进程收到子进程exit(),开始从vfork返回,但是父进程栈都被子进程给return了,父进程无法执行。(注:栈会返回一个诡异的一个栈地址,对于某些内核版本的实现,直接报“栈错误”,然而,对于某些内核版本的实现,于是有可能会再次调用main(),于是进入了一个无限循环的结果,直到vfork调用返回error)

现在回到return和exit,return会释放局部变量,并弹栈,回到上级函数执行。exit直接退掉。return会调用局部对象的析构函数,exit不会。

可见,子进程调用exit()没有修改函数栈,所以,父进程得以顺利执行。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值