zoukankan      html  css  js  c++  java
  • fork,写时复制(copy-on-write),vfork

    fork,写时复制(copy-on-write),vfork

    进程创建

    进程创建分为三种情况
    1.共享
    父进程与子进程共享数据段、堆栈段、代码段,也就是说子进程对数据进行的改变会直接影响父进程。
    2.写时复制(Copy-On-Write)
    我简单地将这种技术理解为,当子进程执行写操作时,内核会将被修改的部分单独copy,单独操作。
    3.直接拷贝
    直接复制父进程的数据段、堆栈段,共享代码段。

    一、fork

    fork()调用时,子进程会复制父进程数据段、堆栈段,并且使用新的物理地址以及虚拟地址存储。但父子进程共享代码段。但现在的实现采用了写时复制技术

    二、vfork

    vfork()调用时,父子进程共享所有资源。但在调度上,使用vfork将保证子进程先于父进程被调度。

    下面给出参考书的代码用以说明两者区别:

    • fork
    	/**********************************************************************
    
    		> File Name: t_fork.c
    
    		> Author: 0nism
    
    		> Email: fd98shadow@sina.com
    
    		> Created Time: Sun 14 Oct 2018 02:41:39 PM CST
    
    	***********************************************************************/
    
    	#include <unistd.h>
    	#include <stdio.h>
    	#include <stdlib.h>
    
    	static int idata = 111;         //  Allocated in data segment
    
    	int main(int argc, char **argv)
    	{
    		int istack = 222;           //  Allocated in stack segment
    		pid_t childPid;
    
    		switch (childPid = fork())
    		{   
    			case -1: 
    					printf("err: fork
    ");
    					return 0;
    
    			case 0:
    					idata *= 3;
    					istack *= 3;
    					break;
    
    			default:
    					sleep(3);
    					break;
    		}   
    
    		printf("PID=%ld %s idata=%d istack=%d
    ", (long)getpid(),
    						(childPid == 0) ? "child " : "parent ", idata, istack);
    
    		exit(EXIT_SUCCESS);
    	}
    

    运行结果为

    	MISlike@10:56:~/process $ ./t_fork 
    	PID=5566 child  idata=333 istack=666
    	PID=5565 parent  idata=111 istack=222
    

    无论是数据段还是堆栈段均完成了复制。

    • vfork
    	/**********************************************************************
    
    		> File Name: t_vfork.c
    
    		> Author: 0nism
    
    		> Email: fd98shadow@sina.com
    
    		> Created Time: Sun 14 Oct 2018 11:21:22 PM CST
    
    	***********************************************************************/
    
    	#include <unistd.h>
    	#include <stdio.h>
    	#include <stdlib.h>
    
    	int main(int argc, char **argv)
    	{
    		int istack = 222;
    
    		switch (vfork())
    		{   
    			case -1: 
    					printf("err: vfork
    ");
    					return 0;
    
    			case 0:                 //  子进程优先执行,在父进程的虚拟地址空间中
    					sleep(3);       //  即使休眠一段时间,父进程仍然不会先执行
    
    					write(STDOUT_FILENO, "Child excuting
    ", 16);
    					istack *= 3;    //  这个变化将会被父进程知晓
    					_exit(EXIT_SUCCESS);
    
    			default:                //  父进程被锁住直到子进程消亡
    					write(STDOUT_FILENO, "Parent excuting
    ", 16);
    					printf("istack = %d
    ", istack);
    					_exit(EXIT_SUCCESS);
    
    		}   
    	}
    

    运行结果如下

    Child excuting
    Parent excuting
    istack = 666
    

    可见子进程操作影响到了父进程,且此时父进程被阻塞,知道子进程消亡或者执行excu()。

  • 相关阅读:
    OpenGL光栅化作业:【bresenham算法】GL_POINTS为基础画圆
    OpenGL光栅化作业:【bresenham算法】GL_POINTS为基础画线段
    GIT 4 (标签)
    用户组 vim yum
    Git (提交版本及版本回退)
    GIT服务器的搭建
    GIT 2 (工作区,暂存库,版本库对比)
    用户的管理
    文档搜索
    GIT 3 (推送与克隆 及 分支管理)
  • 原文地址:https://www.cnblogs.com/0nism/p/9789862.html
Copyright © 2011-2022 走看看