fork与vfork的使用

本文详细解析了fork和vfork系统调用的功能与实现原理,对比了它们之间的区别,包括资源复制方式、进程独立性、并发性及系统开销。并通过实际案例,介绍了如何在Linux环境下使用这些调用来创建子进程。

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

1.fork     创建进程

     函数原型为pid_t fork(void).  函数返回类型为pid_t实质为int 类型。

    fork函数会生成一个新进程,该进程为子进程,调用fork函数的进程为父进程。fork函数调用一次,返回两次。若调用成功,子进程返回0,父进程返回子进程的pid.失败返回-1.fork在生成子进程时用到了写时拷贝技术;不执行一个父进程数据段、堆和栈的完全复制,因为fork之后父子进程共享这些区域,内核将他们的权限设为只读的。如果父子进程中任何一个试图修改这些区域,内核就会将区域所在页拷贝出来。

  • 写时拷贝技术:

   在进行fork复制进程时,并没有马上将父进程空间完全拷贝。而是使用了写时拷贝技术。fork之后,让父进程和子进程共享父进程页面(父子进程共享数据、堆区数据),并将这些数据的权限设置为只读。当父进程或子进程中任意一个试图修改某个页面时,再将这个页面所在页拷贝出来给子进程,然后将拷贝的页和原来页的权限设置为读写。

  优点:这样延缓页面拷贝,提供fork复制效率。通常linux中的新进程都是通过fork+exec实现的。若fork后需要执行exec那么就不需要拷贝。

  fork的实际开销是 复制父进程的页表以及给子进程创建唯一 一个的进程描述符。

2.fork实现原理

    linux通过clone()系统调用实现fork(),这个调用通过一系列参数标明父子进程共享的资源。fork\vfork可根据自己的参数标志调用clone(),然后在有clone()调用do_fork().do_fork()其实已经完成创建的大部分工作,它定义在头文件fork.c中,调用copy_process函数,让进程运行。

  •     首先给进程分配进程描述符,同时为进程创建一个内核栈、task_struct,这些字与当前进程值相同;
  •    系统会检查这个新建进程,即当前拥有的进程数目有没有超过给他分配的资源限制。而且子进程会将自己与父进程分开,进程描述符里许多成员被清0或设为初始值。(注:进程描述符不是继承来的,进程描述符中大多信息是共享的
  •   将子进程设置为不会被运行状态, copy_process()调用copy_flags更新task_struct成员,表明进程是否拥有超级用户权限的标志被清0。设置进程还没有调用exec函数的标志。然后调用get_pid()函数为新进程获取有效pid.
  •    根据传递给clone()的参数标志,copy_process()复制进程实体(共享打开的文件、文件系统信息、信息处理函数、地址空间等)。用父进程在内核上的存在的信息初始化子进程的现场信息,并将eax置0.
  •   将父进程时间片分给子进程一半,进程状态设置为就绪。

3.vfork

  除了不拷贝父进程的页表外, 与fork功能相同。子进程作为一个单独的线程在他的虚拟地址空间运行,父进程被阻塞,直到子进程退出或执行exit().子进程不能像地址空间写入数据。可把vfork当成fork使用。vfork()系统调用的实现通过clone()系统调用传递一个特殊标志进行。

  • 在调用copy_process()时,task_struct的vfor_done成员设置为NULL;
  • 在执行do_fork(),如果给定特殊标志,vfork_done会指向一个特定地址;
  • 子进程先执行后,父进程不是马上恢复执行,而是一直等待,直到子进程通过vfork_done指针向他发送信号;
  • 在调用mm_release()时,该函数用于进程执行内存地址空间,并检查vfork_done是否为空,如果不为空,则向父进程发送信号。
  • 回到do_fork,父进程醒来并返回。

  4.vfork与fork的区别

  •  vfork和fork都是创建一个新进程,vfork是fork的封装得来的;
  • 使用fork创建的子进程他完全复制子进程资源。这样的子进程的独立性高,具有良好的并发性。vfork创建子进程时,操作系统并没有将父进程资源完全复制给子进程,vfork创建的进程共享父进程的地址空间,子进程完全在父进程的地址空间上。子进程对父进程地址空间修改数据时父进程是可以看见的。
  • fork创建一个子进程取决于哪个进程先运行,vfork必须保证子进程先运行,当子进程调用exit或exec时,在调用exit或exec之前进程才有可能被运行。若子进程的调度还要依赖父进程的某个操作,就会导致死锁。
  • 因为fork要将父进程中的代码给完全复制,所以系统开销很大(但fork的开销并不是所以情况都需要的,fork之后调用exec函数,就不会需要写时拷贝技术)。vfork并没将父进程资源全部复制,所以系统开销相对fork要小。
  • vfrok创建一个进程时,以return 0结束为标志,释放局部变量。调用exit(0)是不会释放的。
  • vfork一个子进程,先执行子进程,子进程沿用父进程中的变量,当以exit(0)结束后,父进程可仍沿用子进程中的变量。当以return 0 结束则释放局部变量,父进程再引用时则会为系统给的随机值。

  命令补充:

    查看进程堆栈命令: pstack pid

    查看共享内存:ipcs -m

    查看内存: cat /proc/meminfo

    删除共享内存:ipcrm -m shmid

    查看消息队列:ipcs -q

    查看信号量:ipcs -s 

     查看进程: ps 

    

forkvfork是Linux系统中用来创建进程的函数,它们的区别在于进程的创建和共享数据段的方式。当调用fork函数时,父进程会创建一个子进程,并且子进程会拷贝父进程的数据段。子进程在fork之后会执行父进程的代码,但是父子进程的执行顺序是不确定的。而当调用vfork函数时,父进程会创建一个子进程,但是子进程不会拷贝父进程的数据段,而是父进程共享数据段。在vfork中,子进程会先运行,而父进程会挂起,直到子进程调用了exec或者exit函数,父进程才会被执行。 因此,fork适用于需要在子进程中修改数据的情况,而vfork适用于需要在子进程中立即执行一个新程序的情况。另外,vfork函数的性能比fork函数要好,因为vfork不需要完全拷贝父进程的数据段。然而,由于vfork父进程共享数据段,所以需要注意在子进程中不要修改共享的数据,以免影响到父进程的执行。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [详解linux中forkvfork、clone函数的区别](https://download.youkuaiyun.com/download/weixin_38509656/12844110)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [forkvfork详解](https://blog.youkuaiyun.com/iteye_4389/article/details/82518147)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [fork/vfork详解](https://blog.youkuaiyun.com/weixin_36750623/article/details/83041030)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值