Linux C 中vfork和fork的区别

Linux C 中vfork和fork的区别
我们知道, fork会创建一个新的进程,这个新的进程是当前进程的子进程,区别在于, fork函数会复制父进程的一些资源,也就是,仅仅是复制的关系,而非共享。

而vfork就不同了,利用vfork创建的子进程和父进程共享地址空间,下面,我们通过实际程序来看看:
1、fork函数的简单应用:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int a = 0;
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("error\n");
return -1;
}
else if(0 == pid)
{
printf("child\n");
printf("%d\n" a);
}
else
{
a = 1;
printf("parent\n");
printf("%d\n" a);
}
return 0;
}
运行一下,结果为:
parent
1
child
由此可见,父进程值的修改,不会影响到子进程,为什么呢?因为他们没有共享地址空间啊。

2、我们再看看vfork:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int a = 0;
pid_t pid;
pid = vfork();
if(pid < 0)
{
printf("error\n");
return -1;
}
else if(0 == pid)
{
a = 1;
printf("child\n");
printf("%d\n" a);
_exit(0); // 这个先不管它,以后再说 }
else
{
printf("parent\n");
printf("%d\n" a);
}
return 0;
}
结果为:
child
1
parent
1
可见, vfork创建的子进程和父进程确实共享着内存空间呢。

合集下载

操作系统必备基础知识

操作系统必备基础知识

操作系统必备基础知识今天给大家推荐两份大佬们总结的PDF,一份是计算机基础知识,一份是操作系统,反正帅地看完之后,和面试官聊天,都有点飘了,废话不多说,下面就让小编带你去看看哪些操作系统必备基础知识,希望能帮助到大家!操作系统基础知识操作系统是计算机体系中必不可少的核心系统软件,其他软件(如编辑程序、汇编程序、编译程序、数据库管理系统等系统软件,以及大量应用软件)是建立在操作系统的基础上,并在操作系统的统一管理和支持下运行。

操作系统是用户与计算机之间的桥梁,用户可以通过操作系统提供的功能访问计算机系统中的软硬件资源。

操作系统的作用是通过资源管理提高计算机系统的效率,改善人机界面,为用户提供有好的工作环境。

有效地组织和管理系统中的各种软硬件资源,合理的组织计算机系统工作流程,控制程序的执行,并且向用户提供一个良好的工作环境和友好的接口。

简单的说,操作系统就是运行在计算机硬件和软件(其他系统软件和应用软件)之间的一个系统软件,它的主要作用就是让计算机能够运行的很好的同时让你觉得也不错。

操作系统分为这么几种:批处理操作系统、分时操作系统、实时操作系统、网络操作系统、分布式操作系统、嵌入式操作系统、微机操作系统(这个我们就比较常见了,比如Linux、Windows、Unix、手机上的基于Unix的安卓系统等等)。

操作系统的功能可分为5大部分:处理机(CPU)管理、文件管理、存储管理、设备管理和作业管理。

下面说说处理机管理中的一些基础知识。

三态模型五态模型在多道程序环境的系统中,存在多个可以一起进行(并发执行)的进程,因此必然会存在进程之间的通信问题。

进程间的通信主要有同步、互斥、调度、死锁、信号量机制等问题进程间的同步多个进程都是独立进行的,有的时候需要在某些地方协调一下,比如进程A在生产一个原件,进程B要加工这个原件,这时候就需要进程B等待进程A完成后才能开始进行,这就是进程之间的同步。

进程间的互斥这就是指两个进程都想用同一个资源,但是这个资源同时只能被一个进程使用。

f o r k ( ) 介 绍

f o r k ( ) 介 绍

多进程中的fork一、fork入门知识一个进程,包括代码、数据和分配给进程的资-源。

fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。

一个进程调用fork()函数后,系统先给新的进程分配资-源,例如存储数据和代码的空间。

然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。

相当于克隆了一个自己。

我们来看一个例子:* fork_test.c* version 1* Created on: 2010-5-29* Author: wangth#include unistd.h#include stdio.hint main ()pid_t fpid; --fpid表示fork函数返回的值int count=0;fpid=fork();if (fpid 0)printf("error in fork!");else if (fpid == 0) {printf("i am the child process, my process id is %d-n",getpid());printf("我是爹的儿子-n");--对某些人来说中文看着更直白。

count++;printf("i am the parent process, my process id is %d-n",getpid());printf("我是孩子他爹-n");count++;printf("统计结果是: %d-n",count);return 0;运行结果是:i am the child process, my process id is 5574我是爹的儿子统计结果是: 1i am the parent process, my process id is 5573我是孩子他爹统计结果是: 1在语句fpid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的几乎完全相同,将要执行的下一条语句都是if(fpid0)……为什么两个进程的fpid不同呢,这与fork函数的特性有关。

嵌入式面试笔试题目——附部分答案

嵌入式面试笔试题目——附部分答案

嵌⼊式⾯试笔试题⽬——附部分答案1 、如何⾃动创建设备⽂件?class_create device_create2、led驱动编写有⼏种⽅式?输⼊⼦系统字符设备驱动总线platform led⼦系统3、如何实现http服务器?tcp服务器:socket4、如何编写守护进程,简述syslog的作⽤?第⼀步:创建进程、杀死⽗进程第⼆步:创建新的会话第三步:改变⼯作路径路径第四步:修改⽂件掩码权限第五步:关闭⽂件描述符5、bootloader和uboot的区别?bootloader是启动装载。

这是⼀段很⼩的程序,⽤于在系统上电启动初期运⾏,初始化关键接⼝,如内存,串⼝,关闭中断,关闭看门狗,引导系统进⼊内核的⼀段初始化的程序。

它主要任务就是将内核映像从硬盘读到RAM中,然后跳转到内核的⼊⼝点去运⾏内核,从⽽建⽴系统运⾏的必要环境。

uboot:是bootloader的⼀种6、如何移植uboot?1、下载源码2、解压uboot源码并进⼊⽬录3、指定交叉编译⼯具链4、指定产品BOARD 底板5、编译u-boot7、传感器驱动如何编写?8、BL0,BL1,BL2,BL3的作⽤?BL0 ⽂件是存放在 CPU 内部 IROM 中的⼀段固化代码,CPU 上点之后,⾸先去运⾏soc中的BL0,运⾏时会将 BL1 拷贝到 CPU 的 IRAM 中,然后执⾏BL1;BL1⽂件执⾏起来之后会先进⾏内存的初始化,之后将 BL2 ⽂件拷贝到外部内存中,BL2会初始化BL3的运⾏环境,将BL3搬移到DRAM中,BL3会有⼀个⾃搬移的过程,从⽽启动内核⼊⼝。

BL0:CPU内部的固化代码BL1:三星提供的加密⽂件BL2:截取uboot.bin 前14kBL3:剩下的uboot 执⾏命令以及加载引导内核9、exynos4412 时钟 APLL,MPLL,VPLL的区别?------倍频锁相环APLL:⽤于 CPU_BLK (可产⽣⾼达1.4GHz的频率);作为 MPLL 的补充,它也可以给DMC_BLK 、LEFTBUS_BLK 、RIGHTBUS_BLK 和 CMU_TOP 提供时钟。

Linux中的fork函数

Linux中的fork函数

Linux中的fork函数操作系统实验⼆fork函数作⽤fork函数将运⾏着的程序分成2个(⼏乎)完全⼀样的进程,每个进程都启动⼀个从代码的同⼀位置开始执⾏的线程返回值负值:创建⼦进程失败。

零:返回到新创建的⼦进程。

正值:返回⽗进程或调⽤者。

该值包含新创建的⼦进程的进程ID⽤法pid_t pid=fork();如果创建成功,会有两个进程:⽗进程和⼦进程,fork在这两个进程中分别返回,就是返回两次且返回值不同。

⼀段程序# include<stdio.h># include<sys/types.h># include<unistd.h>int main(){int pid1, pid2;printf("I am father %d! My father is %d.\n", getpid(), getppid());if ((pid1 = fork())<0) //fork return value < 0 , create failed{printf("Child1 fail create!\n");return 1;}else if (pid1 == 0) //fork return value = 0, son is running{printf("I am son %d! My father is %d. \n", getpid(), getppid());return 0;}if ((pid2 = fork())<0){printf("Child2 fail create!\n");return 0;}else if (pid2 == 0){printf("I am daughter %d! My father is %d.\n", getpid(), getppid());return 0;}}编译运⾏gcc fork.c -o fork./fork运⾏结果分析:⾸先是⽗进程,打印了它的⾝份和进程号,还有它的⽗进程号在第⼀个if语句中创建了⼦进程,⼦进程创建成功,返回值是0,执⾏第⼀个else if,打印⾝份是⼦进程和它的进程号和⽗进程号。

对fork函数的理解

对fork函数的理解

对fork函数的理解前言:对于刚刚接触Unix/Linux操作系统,在Linux下编写多进程的人来说,fork 是最难理解的概念之一:它执行一次却返回两个值。

因此,本文着重从以下几个方面来使初学者加深对fork函数的理解和应用:fork函数的机制与特性、fork 函数的两次返回和父子进程的执行顺序介绍、关键字:fork函数、返回值、父进程、子进程正文:一、fork函数的机制与特性1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>45 int main(void)6 {7 pid_t pid;8 if ((pid = fork()) == 00) {9 getchar();10 exit(0);11 }12 getchar ();13}14父进程成功的调用fork(8行)后将会产生一个子进程。

此时会有两个问题:1、子进程的代码从哪里来?2、子进程首次被OS调用时,执行的第一条代码是哪条代码?子进程的代码是父进程代码的一个完全相同拷贝。

事实上不仅仅是text 段,子进程中的全部进程空间都是(包括:text/data/bss/heap/commandline/envir onment)父进程空间的一个完全拷贝。

下一个问题是谁为子进程分配了内存空间?谁复制了父进程空间的内容到子空间?fork当仁不让。

事实上,fork 实现的源代码,由四部分组成:首先,为子进程分配内存空间;然后,将父进程空间的全部内容复制到分配给子进程的内存空间;接着在内核数据结构中创建并正确初始化子进程的PCB (包括两个重要信息:子进程pid,PC 的值=善后代码的第一条指令地址);最后是一段善后代码。

由于子进程的PCB已经产生,因此子进程可以被OS调度子进程首次被OS调度时,执行的第一条代码在fork 内部,不过从引用程序的角度来看,子进程首次被OS调度时,执行的第一条代码是从fork返回。

fork()函数的理解

fork()函数的理解

对于刚刚接触Unix/Linux操作系统,在Linux下编写多进程的人来说,fork是最难理解的概念之一:它执行一次却返回两个值。

首先我们来看下fork函数的原型:#i nclude <sys/types.h>#i nclude <uni ST d.h>pid_t fork(void);返回值:负数:如果出错,则fork()返回-1,此时没有创建新的进程。

最初的进程仍然运行。

零:在子进程中,fork()返回0正数:在负进程中,fork()返回正的子进程的PID其次我们来看下如何利用fork创建子进程。

创建子进程的样板代码如下所示:pid_t child;if((child = fork())<0)/*错误处理*/else if(child == 0)/*这是新进程*/else/*这是最初的父进程*/fock函数调用一次却返回两次;向父进程返回子进程的ID,向子进程中返回0,这是因为父进程可能存在很多过子进程,所以必须通过这个返回的子进程ID来跟踪子进程,而子进程只有一个父进程,他的ID可以通过getppid取得。

下面我们来对比一下两个例子:第一个:#include <unistd.h>#include <stdio.h>int main(){pid_t pid;int count=0;pid = fork();printf( "This is first time, pid = %d\n", pid );printf( "This is sec ON d time, pid = %d\n", pid );count++;printf( "count = %d\n", count );if ( pid>0 ){printf( "This is the parent process,the child has the pid:%d\n", pid );}else if ( !pid ){printf( "This is the child Process.\n")}else{printf( "fork failed.\n" );}printf( "This is third time, pid = %d\n", pid );printf( "This is fouth time, pid = %d\n", pid );return 0;}运行结果如下:问题:这个结果很奇怪了,为什么printf的语句执行两次,而那句“count++;”的语句却只执行了一次接着看:#include <unistd.h>#include <stdio.h>int main(void){pid_t pid;int count=0;pid = fork();printf( "Now, the pid returned by calling fork() is %d\n", pid );if ( pid>0 ){printf( "This is the parent proc ESS,the child has the pid:%d\n", pid );printf( "In the parent process,count = %d\n", count );}else if ( !pid ){printf( "This is the child process.\n");printf( "Do your own things here.\n" );count ++;printf( "In the child process, count = %d\n", count );}else{printf( "fork failed.\n" );}return 0;}运行结果如下:现在来解释上面提出的问题。

Linux 第5章课后习题答案

Linux思考题51.fork()与clone()二者之间得区别就是什么?答:fork创建一个进程时,子进程只就是完全复制父进程得资源,复制出来得子进程有自己得task_struct结构与pid,但却复制父进程其它所有得资源。

通过fork创建子进程,需要将上面描述得每种资源都复制一个副本。

fork()调用执行一次返回两个值,对于父进程,fork函数返回子程序得进程号,而对于子程序,fork函数则返回零,这就就是一个函数返回两次得本质。

在fork之后,子进程与父进程都会继续执行fork调用之后得指令。

系统调用fork()与vfork()就是无参数得,而clone()则带有参数。

fork()就是全部复制,vfork()就是共享内存,而clone()就是则可以将父进程资源有选择地复制给子进程,而没有复制得数据结构则通过指针得复制让子进程共享,具体要复制哪些资源给子进程,由参数列表中得clone_flags来决定。

另外,clone()返回得就是子进程得pid。

2.什么就是进程?什么就是线程?Linux系统中得进程有那些状态?如何获取系统中各进程得状态?答:进程就是指在系统中正在运行得一个应用程序;线程就是系统分配处理器时间资源得基本单元,或者说进程之内独立执行得一个单元。

对于操作系统而言,其调度单元就是线程。

一个进程至少包括一个线程,通常将该线程称为主线程。

一个进程从主线程得执行开始进而创建一个或多个附加线程,就就是所谓基于多线程得多任务。

Linux系统中得进程状态有:TASK_RUNNING(运行状态),TASK_INTERRUPTIBLE(可中断睡眠状态),TASK_UNINTERRUPTIBLE(不可中断得睡眠状态),TASK_STOPPED(暂停状态),TASK_NONINTERACTIVE(不可交互睡眠状态),TASK_DEAD(死亡状态),EXIT_ZOMBIE(僵死进程),EXIT_DEAD(僵死撤销状态)ps 查瞧静态得进程信息可以使用man 来查瞧ps 得使用参数以下就是几个常使用到得,a 显示当前终端得所有进程信息u 使用以用户为主得格式输出进程信息x 显示当前用户在所有终端下得进程信息-e 显示系统内得所有进程# ps 只显示当前用户打开得进程]# ps aux 显示系统中所有进程信息3.Linux系统中进程有哪两种模式?各有何特点?答:用户进程与系统进程,用户进程就就是用户自己打开得应用程序,可有可无。

fork与vfork思考

学习fork与vfrok的一些感悟fork与vfork的区别:一、fork创建的子进程拷贝父进程的数据段,父子进程是相互独立的;而vfork创建的子进程和父进程共享数据段二、fork创建的进程,父子进程执行顺序随机;而vfork创建的子进程优先运行,后运行父进程以上两者初学者都比较清楚的知识点,但根据此知识点看下面的两个程序的运行结果:#include <stdio.h>#include <sys/types.h>#include <unistd.h>int main(void){pid_t pid;int count=3;pid=fork();count++;printf("My ID is %d,and the count is %d\n",getpid(),count);return 0;}此程序会显示的count是4和4,没问题#include <stdio.h>#include <sys/types.h>#include <unistd.h>int main(void){pid_t pid;int count=3;pid=vfork();count++;printf("My ID is %d,and the count is %d\n",getpid(),count);return 0;}此程序会显示4和1,并且会提示有Bus error#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <unistd.h>int main(void){pid_t pid;int count=3;pid=vfork();count++;printf("My ID is %d,and the count is %d\n",getpid(),count);_exit(0);}此时程序count的结果是4和5,且不报任何错误由此大家会开始纳闷了,我考虑了很久同时查找相关的资料,得到一些感想:首先,对于第一个程序,fork创建的父子程序数据段独立,在任一进程执行完后,会执行return 0语句,这样自己进程里的变量会被系统收回,而另一进程由于有自己独立的数据段故不会受此影响,结果正确然后,根据上述理论分析第二个程序,vfork创建子进程,父子进程是共享数据段的,且子进程先运行,当子进程运行到return 0后,就将公共数据区里的count变量收回。

fork clone 和 fork 的区别

fork/vfork/clone分类:Linux系统C++2010-08-27 09:51 34人阅读评论(0) 收藏举报首先说明Linux下的进程与线程比较相近。

这么说的一个原因是它们都需要相同的数据结构来表示,即task_struct。

区别在于一个有独立的用户空间,一个是共享的用户空间(如果完全没有用户空间则是内核线程,不需要)。

Linux的用户进程不能直接被创建出来,因为不存在这样的API。

它只能从某个进程中复制出来,再通过exec这样的API来切换到实际想要运行的程序文件。

复制的API包括三种:fork、clone、vfork。

这三个API的内部实际都是调用一个内核内部函数do_fork,只是填写的参数不同而已。

vfork,其实就是fork的部分过程,用以简化并提高效率。

而fork与clone是区别的。

fork是进程资源的完全复制,包括进程的PCB、线程的系统堆栈、进程的用户空间、进程打开的设备等。

而在clone中其实只有前两项是被复制了的,后两项都与父进程共享。

在四项资源的复制中,用户空间是相对庞大的,如果完全复制则效率会很低。

在Linux中采用的“写时复制”技术,也就是说,fork执行时并不真正复制用户空间的所有页面,而只是复制页面表。

这样,无论父进程还是子进程,当发生用户空间的写操作时,都会引发“写复制”操作,而另行分配一块可用的用户空间,使其完全独立。

这是一种提高效率的非常有效的方法。

而对于clone来说,它们连这些页面表都是与父进程共享,故而是真正意义上的共享,因此对共享数据的保护必须有上层应用来保证。

1. fork, vfork and clone三者最终都会调用do_fork函数,三者的差别就是参数上的不同而已。

fork的实现:do_fork(CLONE_SIGCHLD,...)clone的实现:do_fork(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGCHLD,...)vfork的实现:do_fork(CLONE_VFORK|CLONE_VM|CLONE_SIGCHLD,...)2. Linux使用copy on wirte的技术,Linux中的fork代价仅仅是创建子进程的页表结构和创建一个task_struct结构。

f o r k ( ) 介 绍 ( 2 0 2 0 )

fork函数与vfork函数的区别与联系详解创建一【导师实操追-女教-程】个新进程的方法只有由某个已存在的进程调用fork()或vfork(),当然某些进程如init等是作为系统启动的一部分【Q】而被内核创建的。

1.f【1】ork函数介绍#in【0】clude?#inc【⒈】lude?pid【6】_t fork (void );正确返回【9】:父进程中返回子进程的进程号;子进程中返回0;(单调用双返【5】回函数)错误返回【2】:-1;子进程是【б】父进程的一个拷贝。

具体说,子进程从父进程那得到了数据段和堆栈段,但不是与父进程共享而是单独分配内存。

fork函数返回后,子进程和父进程都是从fork函数的下一条语句开始执行。

由于子进程与父进程的运行是无关的,父进程可先于子进程运行,子进程也可先于父进程运行,所以下段程序可以有两种运行结果。

[root@happy src]# cat simplefork.c#include?#include?#includeint globa = 4;int main (void )pid_t pid;int vari = 5;printf ("before fork" );if ((pid = fork()) 0){printf ("fork error");exit (0);else if (pid == 0){globa++ ;printf("Child changed");printf("Parent did not changde");printf("globa = %d vari = %d",globa,vari); exit(0);运行结果:(可能出现的一种结果)[root@happy src]# .-a.outbefore forkChild changedgloba = 5 vari = 4Parent did not changdegloba = 4 vari = 52.vfork函数介绍vfork创建新进程的主要目的在于用exec函数执行另外的程序,实际上,在没调用exec或exit之前子进程的运行中是与父进程共享数据段的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档