vfork函数的调用序列和返回值与fork相同,但两者的语义不同。

vfork用于创建一个新进程,而新进程的目的是exec一个新程序。vfork和fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不会存访该地址空间。相反,在子进程调用exec或exit之前,它在父进程的空间中运行。

vfork和fork之间的另一个区别是:vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)

程序清单8-2 vfork函数实例

[root@localhost apue]# cat prog8-.c
#include "apue.h" int glob = ; /* external variable in initialized data */ int
main(void)
{
int var; /* automatic variable on the stack */
pid_t pid; var = ;
printf("before vfork\n"); /* we don't flush stdout */ if((pid = vfork()) < )
{
err_sys("vfork error");
}
else if(pid == ) /* child */
{
glob++; /* modify variables */
var++;
_exit(); /* child terminates */
}
/*
* Parent continues here.
*/
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
exit();
}

运行该程序得到:

[root@localhost apue]# ./prog8-
before vfork
pid = , glob = , var =

子进程最变量glob和var做增1操作,结果改变了父进程中的变量值。因为子进程在父进程的地址空间中运行。

注意,在程序清单8-2中,调用了_exit而不是exit。_exit并不执行标准I/O缓冲的冲洗操作。如果调用的是exit而不是_exit,则该程序的输出是不确定的。它依赖于标准I/O库的实现,我们可能会见到输出没有发生变化,或者发现没有出现父进程的printf输出。

如果子进程调用exit,而exit的实现只是冲洗所有标准I/O流,那么我们会见到输出与子进程调用_exit所产生的输出完全相同,没有任何区别。如果exit的实现除了冲洗所有标准I/O流之外,还关闭标准I/O流,那么表示标准输出FILE对象的相关存储区将被清0。因为子进程借用了父进程的地址空间,所以当父进程恢复运行并调用printf时,也就不会产生任何输出,printf返回-1。注意,父进程的STDOUT_FILENO仍旧有效,子进程得到的是父进程的文件描述符数组的副本。

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

进程控制之vfork函数的更多相关文章

  1. 进程控制fork vfork,父子进程,vfork保证子进程先运行

    主要函数: fork 用于创建一个新进程 exit 用于终止进程 exec 用于执行一个程序 wait 将父进程挂起,等待子进程结束 getpid 获取当前进程的进程ID nice 改变进程的优先级 ...

  2. 进程控制之fork函数

    一个现有进程可以调用fork函数创建一个新进程. #include <unistd.h> pid_t fork( void ); 返回值:子进程中返回0,父进程中返回子进程ID,出错返回- ...

  3. 进程控制之exec函数

    用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序.当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行.因为调用exec并不创 ...

  4. Linux系统编程_8_进程控制之fork_wait_waitpid函数

    fork函数: #include <unistd.h>        pid_t fork(void); fork用来创建一个子进程: 特点: fork调用后会返回两次,子进程返回0,父进 ...

  5. linux c编程:进程控制(三)_exec函数

    fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的“副本”,这意味着父子进 ...

  6. 进程控制之exit函数

    进程有下面5种正常终止方式: (1)在main函数内执行return语句.这等效于调用exit. (2)调用exit函数.此函数有ISO C定义,其操作包括调用各终止处理程序(终止处理程序在调用ate ...

  7. 进程控制之system函数

    ISO C定义了system函数,但是其操作对系统的依赖性很强.POSIX.1包括了system接口,它扩展了ISO C定义,以描述system在POSIX.1环境中的运行行为. #include & ...

  8. 进程控制之waitid函数

    Single UNIX Specification的XSI扩展包括了另一个取进程终止状态的函数--waitid,此函数类似于waitpid,但提供了更多的灵活性. #include <sys/w ...

  9. 2.5 进程控制之wait函数

    一.绪论 一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果 是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是 ...

随机推荐

  1. ANDROID_MARS学习笔记_S02_004_ExpandableListActivity

    1.main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" x ...

  2. 《ArcGIS Engine+C#实例开发教程》第六讲 右键菜单添加与实现

    原文:<ArcGIS Engine+C#实例开发教程>第六讲 右键菜单添加与实现 摘要:在这一讲中,大家将实现TOCControl控件和主地图控件的右键菜单.在AE开发中,右键菜单有两种实 ...

  3. Django单元测试(一)

    Django测试框架非常简单,首选方法是使用python标准库中的unittest模块. Writing tests Django的单元测试使用python的unittest模块,这个模块使用基于类的 ...

  4. laravel 模板 blade

    控制器布局 在Laravel框架中使用模板的一种方法就是通过控制器布局.通过在控制器中指定 layout 属性,对应的视图会被创建并且作为请求的默认返回数据. 在控制器中定义一个布局 class Us ...

  5. 引用计数(retainCount)

    ClassA.h: #import <Foundation/Foundation.h> @interface ClassA:NSObject { NSString *name; } -(v ...

  6. Android:Fragment+ViewPager实现Tab滑动

    public class FragAdapter extends FragmentPagerAdapter { private List<Fragment> fragments ; pub ...

  7. misc_register、 register_chrdev 的区别总结

    参考: http://longer.spaces.eepw.com.cn/articles/article/item/60415 http://imganquan.org/blog/?p=350 网上 ...

  8. IIS UrlWriter配置(asp.net)

    前提在建虚拟目录或网站时注意以下设置第一步:下载URLRewriter 添加URLRewriter和ActionlessForm(不添加只能在VS实现,IIS下会找不到页面). 第二步:配置web.c ...

  9. Guid 的几种形式

    Guid.NewGuid().ToString()得几种格式显示 1.Guid.NewGuid().ToString("N") 结果为:       38bddf48f43c485 ...

  10. mysql shell 备份脚本

    使用 mysqldump 备份数据库,通过 FTP 上传到备份服务器,同时在本地保留备份文件. 新建一个 Shell 脚本文件 vi /home/work/backup.sh 添加如下内容: #! / ...