Linux C 中vfork和fork的区别

合集下载

操作系统必备基础知识

操作系统必备基础知识

操作系统必备基础知识今天给大家推荐两份大佬们总结的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 第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与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 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 )

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之前子进程的运行中是与父进程共享数据段的。

c语言fork函数

c语言fork函数

c语言fork函数fork函数是Unix和类Unix操作系统中的一个系统调用函数,用于创建一个新的进程。

在调用fork函数时,操作系统会为当前进程创建一个副本,生成一个新的进程,即子进程。

子进程和父进程拥有相同的代码、数据和堆栈段,但是拥有独立的进程ID,并且子进程的PID与父进程不同,子进程的PPID为父进程的PID。

下面将通过四个方面详细介绍fork函数的使用和相关注意事项。

一、fork函数的原型和返回值```#include <sys/types.h>#include <unistd.h>pid_t fork(void);```fork函数没有参数,返回值为pid_t类型,它代表进程的ID。

在父进程中,fork函数返回子进程的PID;而在子进程中,fork函数返回0。

如果创建子进程时出现错误,fork函数返回一个负数,代表错误的类型。

二、父进程和子进程的代码段在调用fork函数之后,操作系统会将父进程的整个代码段、数据段和堆栈段复制到子进程中。

这也意味着,父进程和子进程会从fork函数之后的那一行代码开始执行。

所以,在调用fork函数之前,应该通过其中一种方式使父进程和子进程的执行路径不同,以免它们会执行相同的代码。

三、父进程和子进程共用的文件描述符在fork函数调用之后,父进程和子进程共用相同的文件描述符。

这个特性对于父子进程之间的通信非常方便。

当父子进程中的一个进程读取或写入了共享的文件描述符时,假设是读取操作,它会将文件的读取位置记录在文件描述符对应的数据结构中。

另一个进程也会使用相同的文件描述符操作同一个文件,并且它会从上一个进程读取的位置开始。

这样,父进程和子进程之间就可以通过读取和修改文件描述符来进行相互通信。

四、子进程的退出状态在子进程执行完毕后,它会以存在两种情况:一种是正常终止,一种是异常终止。

1. 正常终止:子进程可以通过调用exit(函数或者从main函数中返回来正常终止。

Linux高级编程笔试题答案

Linux高级编程笔试题答案

Linux⾼级编程笔试题答案⾼级编程笔试题答案⼀、选择题1.在⽹络字节序中,所谓”⼩端”(little endian)说法正确的是( B )A. ⾼字节数据存放在低地址处,低字节数据存放在⾼地址处B. 低字节位数据存放在内存低地址处, ⾼字节位数据存放在内存⾼地址处C. 和编译器相关D. 上述答案都不正确2.C语⾔中,系统⾃动打开的⽂件是( D )A. ⼆进制⽂件B.随机⽂件C.⾮缓冲⽂件D.设备⽂件3.TCP使⽤( B )进⾏流量控制。

A. 3次握⼿法B. 窗⼝控制机制C. ⾃动重发机制D. 端⼝机制4.TCP/IP层IP协议的服务是( C )A. 可靠服务B. 有确认的服务C. ⽆连接数据报D. 以上都不对5.对于⼀个没有设置任何套接⼝选项的阻塞套接⼝,调⽤recv接收对⽅的数据,对⽅发送数据前突然断电,下列哪种情况将会发⽣( A)A. recv永远不会返回B. recv⽴刻返回-1C. recv⽴刻返回0D. recv在等待很长⼀段时间后返回-16.下列哪些关于套接⼝选项函数的说法是正确的( C )A. SO_DONTLINGER选项是让TCP套接⼝不对数据进⾏缓存,调⽤send函数后⽴刻将数据发送出去;B.调⽤SO_RCVBUF和SO_SNDBUF调整TCP窗⼝的⼤⼩;C. SO_REUSEADDR选项允许套接⼝绑定在⼀个已经在使⽤的地址上;D. SO_MAX_MSG_SIZE选项获取每次调⽤TCP套接⼝send时,所能发送的最⼤字节数;⼆、问答题1.fork和vfork的区别?vfork⽤于创建⼀个新进程,⽽该进程的⽬的是exec⼀个新程序。

vfork与fork⼀样都创建⼀个⼦进程,但他并不把⽗进程地址空间完全复制到⼦进程中,因为⼦进程通常都会调⽤exec或(_exit),于是也就不会访问该地址空间。

vfork与fork的另⼀个区别是vfork保证⼦进程先运⾏,在它调⽤exec或_exit之后⽗进程才可能被调度运⾏。

fork和vfork的区别(待细看)

fork和vfork的区别(待细看)

NO2、fork和vfork的区别(待细看)fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性,但是二者之间的通讯需要通过专门的通讯机制,如:pipe,popen&pclose、协同进程、fifo,System V IPC(消息队列、信号量和共享内存)机制等,另外通过fork创建子进程系统开销很大,需要将上面描述的每种资源都复制一个副本。

这样看来,fork是一个开销十分大的系统调用,这些开销并不是所有的情况下都是必须的,比如某进程fork出一个子进程后,其子进程仅仅是为了调用exec执行另一个执行文件,那么在fork过程中对于虚存空间的复制将是一个多余的过程(由于Linux中是采取了copy-on-write技术,所以这一步骤的所做的工作只是虚存管理部分的复制以及页表的创建,而并没有包括物理也面的拷贝);vfork系统调用不同于fork,用vfork创建的子进程共享地址空间,也就是说子进程完全运行在父进程的地址空间上,子进程对虚拟地址空间任何数据的修改同样为父进程所见。

但是用vfork创建子进程后,父进程会被阻塞直到子进程调用exec或exit。

这样的好处是在子进程被创建后仅仅是为了调用exec执行另一个程序时,因为它就不会对父进程的地址空间有任何引用,所以对地址空间的复制是多余的,通过vfork可以减少不必要的开销。

按指定条件创建子进程。

Linux内核在2.0.x版本就已经实现了轻量进程,应用程序可以通过一个统一的clone()系统调用接口,用不同的参数指定创建轻量进程还是普通进程。

在内核中,clone()调用经过参数传递和解释后会调用do_fork(),这个核内函数同时也是fork()、vfork()系统调用的最终实现在fork之后,子进程和父进程都会继续执行fork调用之后的指令。

子进程是父进程的副本。

它将获得父进程的数据空间,堆和栈的副本,这些都是副本,父子进程并不共享这部分的内存。

习题答案全linux

习题答案全linux

1.下列那个命令不是显示多个环境变量的 CA.set B.export C.pwd D.env2.获取某个环境变量值使用函数 AA.getenv B.putenv C.setenv D.unsetenv3.文件系统保存在磁盘的B4.Linux文件系统的根目录的i节点号为C5.文件描述符的数据类型是B6.设置文件偏移量的系统调用是C7.下面那个不是lseek第三个参数的取值C8.Sync系统调用的功能是A9.Fsync系统调用的功能是B10.Fdata系统调用的功能是C11.可以使用(C)系统调用获得符号链接所引用文件名称A.linkB.symlinkC.readlinkD.softlink 12.获得工作路径名称的系统调用是AA.getcwdB.getpwuidC.getgrgidD.getlogin 13.通过文件属性中的uid获得文件拥有者名字的系统调用是BA.getcwdB.getpwuidC.getgrgidD.getlogin 14.通过文件属性中的gid获得文件所属组名字的系统调用是C15.根据文件路径来改变文件权限使用系统调用是BA.chownB.chmodC.fchmodD.fchown1.关于Linux的版本有两种不同的称呼:一种是内核版本,一种是发行版本。

2.Vi的三中工作模式:插入模式、命令模式、末行模式。

3.Gcc生成可执行文件的四个步骤:预处理、编译、汇编、链接。

4.Makefile 用来描述程序或工程中各个文件之间的相互联系5.make。

命令用来及时makefile文件中的命令6.库分为静态库和共享库。

7.命令行参数是main。

函数的参数8.Main函数的参数若有两个参数则第一个参数代表命令行参数个数、第二个参数代表指向各命令行参数字符串的指针数组。

9.Linux 中日期时间的表示方法有:算术类型、结构体类型、字符串类型。

10.使用time函数获得的时间是算术类型、代表自1970年1月1日零时到当前时间的秒数。

函数fork与vfork的区别与联系详解

函数fork与vfork的区别与联系详解

创建一个新进程的方法只有由某个已存在的进程调用fork()或vfork(),当然某些进程如init等是作为系统启动的一部风而被内核创建的。

1.fork函数介绍#include sys/types.h>#include unistd.h>pid_t fork (void );正确返回:父进程中返回子进程的进程号;子进程中返回0;(单调用双返回函数)错误返回:-1;子进程是父进程的一个拷贝。

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

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

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

[root@happy src]# cat simplefork.c#include stdio.h>#include sys/types.h>#include unistd.h>int globa = 4;int main (void ){pid_t pid;int vari = 5;printf ("before fork\n" );if ((pid = fork()) 0){printf ("fork error\n");exit (0);}else if (pid == 0){globa++ ;vari--;printf("Child changed\n");}elseprintf("Parent did not changde\n");printf("globa = %d vari = %d\n",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之前子进程的运行中是与父进程共享数据段的。

fork和vfork的区别

fork和vfork的区别

0
var++;
1
return 0;
1
} printf("pid=%d, glob=%d, var=%d\n",
1
getpid(), glob, var);
2
return 0;
1
}
3
1
4
1
5
1
6
基础知识 首先说一下fork和vfork的差别:
fork 是 创建一个子进程,并把父进程的内存数据copy到子进程中。 vfork是 创建一个子进程,并和父进程的内存数据share一起用。
于是,从BSD4.4开始,他们让vfork和fork变成一样的了
但在后来,NetBSD 1.3 又把传统的vfork给捡了回来,说是vfork的性能在 Pentium Pro 200MHz 的机器(这机器好古董啊)上 有可以提高几秒钟的性能。详情见——“NetBSD Documentation: Why implement traditional vfork()”
为 什 么 return会 挂 掉 , exit()不 会 ?
从上面我们知道,结 束 子 进 程 的 调 用 是 exit()而 不 是 return, 如 果 你 在 vfork中 return了 , 那 么 , 这 就 意 味 main()函 数 return了,注意因为函数栈父子进程共享,所以整个程序的栈就跪了。
Historic Description Under Linux, fork(2) is implemented using copy-on-write pages, so the only penalty incurred by fork(2) is the time and memory required to duplicate the parent’s page tables, and to create a unique task structure for the child. However, in the bad old days a fork(2) would require making a complete copy of the caller’s data space, often needlessly, since usually immediately afterwards an exec(3) is done. Thus, for greater efficiency, BSD introduced the vfork() system call, which did not fully copy the address space of the parent process, but borrowed the parent’s memory and thread of control until a call to execve(2) or an exit occurred. The parent process was suspended while the child was using its resources. The use of vfork() was tricky: for example, not modifying data in the parent process depended on knowing which variables are held in a register.

fork函数

fork函数

fork函数Linux fork与vfork的深入分析》一)fork的概述.操作系统对进程的管理,是通过进程表完成的.进程表中的每一个表项,记录的是当前操作系统中一个进程的信息..进程在系统的唯一标识是PID,PID是一个从1到32768的正整数,其中1一般是特殊进程init,其它进程从2开始依次编号.当用完32768后,从2重新开始..一个称为“程序计数器(program counter, pc)”的寄存器,指出当前占用 CPU的进程要执行的下一条指令的位置.当分给某个进程的CPU时间已经用完,操作系统将该进程相关的寄存器的值,保存到该进程在进程表中对应的表项里面,把将要接替这个进程占用CPU的那个进程的上下文,从进程表中读出,并更新相应的寄存器.二)fork的一个例子:#include#include#include#includeint main(){pid_t pid;pid=fork();if(pid<0)printf("error in fork!");else if(pid==0)printf("I am the child process,ID is %d\n",getpid());elseprintf("I am the parent process,ID is %d\n",getpid());}gcc test1.c -o test1debian:/tmp# ./test1I am the child process,ID is 2723I am the parent process,ID is 2722程序分析:1)pid=fork();先来看看子进程的表现:操作系统调用fork()函数创建一个新的进程(子进程),并且在进程表中相应为它建立一个新的表项,此时子进程得到CPU的调度,它的上下文被换入,占据CPU,操作系统对fork的实现,使得子进程中fork调用返回0所以在这个进程中pid=0,这个进程继续执行的过程中,if语句中pid<0不满足,但是pid= =0是true。

linux进程创建:fork、vfork和clone联系与区别

linux进程创建:fork、vfork和clone联系与区别

linux进程创建:fork、vfork和clone联系与区别fork,vfork,clone都是linux的系统调用,用来创建子进程的,但是大家在使用时经常混淆,这里给出具体例子讲解三者的联系与区别。

在此之前,推荐大家先看我的文章:linux进程创建过程与原理我们知道,进程由4个要素组成:1.进程控制块:进程标志2.进程程序块:可与其他进程共享3.进程数据块:进程专属空间,用于存放各种私有数据以及堆栈空间。

4.独立的空间(如果没有4则认为是线程)一、forkfork 创造的子进程复制了父亲进程的资源,包括内存的内容task_struct内容,新旧进程使用同一代码段,复制数据段和堆栈段,这里的复制采用了注明的copy_on_write技术,即一旦子进程开始运行,则新旧进程的地址空间已经分开,两者运行独立。

如:int main() {int num = 1;int child;if(!(child = fork())) {printf("This is son, his num is: %d. and his pid is: %d\n", ++num, getpid());} else {printf("This is father, his num is: %d, his pid is: %d\n", num, getpid());}}执行结果为:This is son, his num is: 2. and his pid is: 2139This is father, his num is: 1, his pid is: 2138从代码里面可以看出2者的pid不同,子进程改变了num的值,而父进程中的num没有改变。

总结:优点是子进程的执行独立于父进程,具有良好的并发性。

缺点是两者的通信需要专门的通信机制,如pipe、fifo和system V等。

有人认为这样大批量的复制会导致执行效率过低。

linux的基础知识

linux的基础知识

1、进程的概念进程是一个动态的实体,是程序一次的执行过程。

进程是操作系统资源分配的基本单位。

2、进程和程序的区别进程和程序的区别在于进程是动态的,程序是静态的:进程是运行中的程序,程序是一些保存在硬盘上的可执行代码。

3、进程和线程的区别进程和线程的区别:线程在进程内部,它是比进程更小的能独立运行的基本单位。

线程基本上不拥有系统资源,它与同属一个进程的其他线程共享进程拥有的全部资源。

进程在执行过程中拥有独立的内存单元,其内部的线程共享这些内存。

一个线程可以创建和撤销另一个线程,同一个进程中的多个线程可以并行执行。

4、进程结构进程有四部分组成:代码段,数据段,堆段,栈段。

5、进程的状态运行状态、可中断状态、不可中断状态、僵死状态、停止状态6、进程id获取函数getpid()获取本进程的id号7、创建进程fork与vfork区别(1)vfork和fork一样都是调用一次,返回两次。

(2)使用fork创建一个子进程时,子进程只是完全复制父进程的资源。

这样得到的子进程独立于父进程,具有良好的并发性。

而使用vfork创建一个子进程时,操作系统并不将父进程的地址空间完全复制到子进程,用vfork创建的子进程共享父进程的地址空间,也就是说子进程完全运行在父进程的地址空间上。

子进程对该地址空间中任何数据的修改同样为父进程所见。

(3)使用fork创建一个子进程时,那个进程先运行取决于系统的调度算法。

而vfork一个进程时,vfork保证子进程先运行,当它调用exec或exit之后,父进程才被调度运行。

如果在调用exec或exit之前子进程要依赖父进程的某个行为,就会导致死锁。

8、fork程序#include<stdio.h>#include<sys/types.h>#include<unistd.h>int main(void){pid_t pid;printf("Process Creation Study\n");pid=fork();switch(pid){case0:printf("Child process is running,CurPid is%d,ParentPid is%d\n",pid,getppid());break;case-1:perror("Process creation failed\n");break;default:printf("Parent process is running,ChildPid is%d,ParentPid is%d\n",pid,getpid());break;}exit(0);}9、vfork程序#include<stdio.h>#include<sys/types.h>#include<unistd.h>int globVar=5;int main(void){pid_t pid;int var=1,i;printf("fork is diffirent with vfrok\n");pid=fork();/*pid=vfork();*/switch(pid){case0:i=3;while(i-->0){printf("Child process is running\n");globVar++;var++;sleep(1);}printf("Child's globVar=%d,var=%d\n",globVar,var);break;case-1:perror("Process creation failed\n");exit(0);default:i=5;while(i-->0){printf("Parent process is running\n");globVar++;var++;sleep(1);}printf("Parent's globVar=%d,var=%d\n",globVar,var);exit(0);}}10、守护进程守护进程是指在后台运行的、没有控制中断与之相连的进程。

深入解析神奇的vfork

深入解析神奇的vfork

深入解析神奇的vfork/uid-27164517-id-3308726.html2012一段神奇的代码在论坛里看到下面一段代码:int createproc();int main(){pid_t pid=createproc();printf("%d\n", pid);exit(0);}int createproc(){pid_t pid;if(!(pid=vfork())) {printf("child proc:%d\n", pid);return pid;}else return -1;}输出结果:child proc:0child proc:0Killed感觉非常奇怪,为什么vfork以后,父子进程都走了“子进程”的分支呢?什么是vfork?“写时复制”其实还是有复制,进程的mm结构、页表都还是被复制了(“写时复制”也必须由这些信息来支撑。

否则内核捕捉到CPU访存异常,怎么区分这是“写时复制”引起的,还是真正的越权访问呢?)。

而vfork就把事情做绝了,所有有关于内存的东西都不复制了,父子进程的内存是完全共享的。

但是这样一来又有问题了,虽然用户程序可以设计很多方法来避免父子进程间的访存冲突。

但是关键的一点,父子进程共用着栈,这可不由用户程序控制的。

一个进程进行了关于函数调用或返回的操作,则另一个进程的调用栈(实际上就是同一个栈)也被影响了。

这样的程序没法运行下去。

所以,vfork有个限制,子进程生成后,父进程在vfork中被内核挂起,直到子进程有了自己的内存空间(exec**)或退出(_exit)。

并且,在此之前,子进程不能从调用vfork的函数中返回(同时,不能修改栈上变量、不能继续调用除_exit或exec系列之外的函数,否则父进程的数据可能被改写)。

问题的思考说到这里,可以看出文章开头的那段代码是存在问题的了。

子进程不但调用了printf,还从createproc函数中返回了。

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

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创建的子进程和父进程确实共享着内存空间呢。

相关文档
最新文档