fork和vfork,exec
一.fork:子进程是父进程的一个拷贝,子进程获得同父进程相同的数据,但是同父进程使用不同的数据段和堆栈段。
特点:调用一次,返回两次。成功则在父进程中返回子进程ID,在子进程中返回0。失败则返回-1。
返回后都执行fork之后的语句。
例如:创建4个子进程,每个子进程都输出自己的pid和父进程的pid
#include <stdio.h>
#include <unistd.h>
int main()
{
int pid ;
for(int i = ;i < ;i++)
{
pid = fork();
if(pid == ) break;
}
if(pid == )
{
printf("i am child mypid:%d,myparentpid:%d\n",getpid(),getppid());
}else if(pid > )
{
printf("i am parent mypid:%d,myparentpid:%d\n",getpid(),getppid());
while();
}
else
{
perror("call fork failed\n");
exit(1);
}
}
在for循环中我们要判断是否为子进程,是子进程的话要跳出。因为子进程将父进程的i值拷贝过来,然后从fork语句的下一句开始执行。即}就会继续创建子进程,直到系统满了才停止。
运行结果:

父进程和子进程的输出顺序时可以变化的
我们可以看到父进程的pid是bash,这个问题我们下面再讨论。
二.vfork 和exec
vfork 系统调用创建的进程共享其父进程的内存地址空间,但是并不完全复制父进程的数据段,而是和父进程共享其数据段。为了防止父进程重写子进程需要的数据,父进程会被 vfork 调用阻塞,直到子进程退出或执行一个新的程序。由于调用 vfork 函数时父进程被挂起,所以如果我们使用 vfork 函数替换 forkdemo 中的 fork 函数,那么执行程序时输出信息的顺序就不会变化了。
exec:调用exec后,不会执行程序之后的代码。
exec不创建新的程序
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
execve才是真正的系统调用 ,其他的函数都是调用它执行。
如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错则返回-1,所以exec函数只有出错的返回值而没有成功的返回值.
函数名虽然看起来难记,但每个字母都有自己的意义,了解之后就不难记了:
对于带字母p的函数: 如果参数中包含/,则将其视为路径名。 否则视为不带路径的程序名,在PATH环境变量的目录列表中搜索这个程序。
函数名字中带字母 "l" 的表示其参数个数不确定,带字母 "v" 的表示使用字符串数组指针 argv 指向参数列表。
函数名字中含有字母 "p" 的表示可以自动在环境变量 PATH 指定的路径中搜索要执行的程序。
函数名字中含有字母 "e" 的函数比其它函数多一个参数 envp。该参数是字符串数组指针,用于指定环境变量。调用这样的函数时,可以由用户自行设定子进程的环境变量,存放在参数 envp 所指向的字符串数组中。
简洁版:
l 命令行参数列表
p 搜素file时使用path变量
v 使用命令行参数数组
e 使用环境变量数组,不使用进程原有的环境变量,设置新加载程序运行的环境变量

举例:
char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execv("/bin/ps",ps_argv);
execle("/bin/ps","ps","-o","pid,ppid,pgrp,session,tpgid,comm",NULL,ps_envp);
execve("/bin/ps",ps_argv,ps_envp);
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL); //第一个是程序名,第二个是命令行参数
execvp("ps", ps_argv);
上面说的app的父进程是bash ,我们在终端键入./app 是bash fork一个新的进程,这个进程执行的代码时用exec执行我们键入的路径程序。
fork和vfork,exec的更多相关文章
- Linux下fork()、vfork()、clone()和exec()的区别
		
转自Linux下fork().vfork().clone()和exec()的区别 前三个和最后一个是两个类型.前三个主要是Linux用来创建新的进程(线程)而设计的,exec()系列函数则是用来用指定 ...
 - 1.2   Linux中的进程 --- fork、vfork、exec函数族、进程退出方式、守护进程等分析
		
fork和vfork分析: 在fork还没有实现copy on write之前,Unix设计者很关心fork之后立即执行exec所造成的地址空间浪费,也就是拷贝进程地址空间时的效率问题,所以引入vfo ...
 - fork()、vfork()、clone()和exec()
		
前三个和最后一个是两个类型.前三个主要是Linux用来创建新的进程(线程)而设计的,exec()系列函数则是用来用指定的程序替换当前进程的所有内容.所以exec()系列函数经常在前三个函数使用之后调用 ...
 - fork()和vfork()的区别,signal函数用法,exec()系列函数的用法小结
		
一:fork()和vfork()的区别: fork()函数可以创建子进程,有两个返回值,即调用一次返回两个值,一个是父进程调用fork()后的返回值,该返回值是刚刚创建的子进程的ID;另一个是子 ...
 - fork与vfork
		
先看一个fork的例子: ; int main(void) { int var, pid; ; ) { printf("vfork error"); exit(-); } ) { ...
 - fork、vfork、clone区别
		
在Linux中主要提供了fork.vfork.clone三个进程创建方法. 问题 在linux源码中这三个调用的执行过程是执行fork(),vfork(),clone()时,通过一个系统调用表映射到s ...
 - 进程创建函数fork()、vfork() ,以及excel()函数
		
一.进程的创建步骤以及创建函数的介绍 1.使用fork()或者vfork()函数创建新的进程 2.条用exec函数族修改创建的进程.使用fork()创建出来的进程是当前进程的完全复制,然而我们创建进程 ...
 - fork与vfork详解
		
一.fork函数 要创建一个进程,最基本的系统调用是fork,系统调用fork用于派生一个进程,函数原型如下: pid_t fork(void) 若成功,父进程中返回子进程ID,子进程中返回0,若出 ...
 - linux 进程创建clone、fork与vfork
		
目录: 1.clone.fork与vfork介绍 2.fork说明 3.vfork说明 4.clone说明5.fork,vfork,clone的区别 内容: 1.clone.fork与vfork介绍 ...
 - UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid
		
本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID 1 进程标识符(Process Identifie ...
 
随机推荐
- cocos2d-x 3.2 关闭按钮点击立马销毁自己报错
			
cocos2d-x 3.2 Button点击事件里调用移除当前层报错 http://www.th7.cn/program/ios/201408/271227.shtml 诡异的错误,点击关闭按钮,居然 ...
 - 我的 Git 学习过程
			
我的 Git 学习过程 有 SVN 使用基础. 开始使用 FastAdmin 后正式使用 Git. 找了一篇廖雪峰的 <Git 教程> 找到一个在线学习 Git 的教程 https://l ...
 - FastAdmin 开发时出错的调试
			
第一步:打开 FastAdmin Debug 打开 Debug. 第二步:打开浏览器控制器 打开浏览器控制器,并按 F5 重新加载页面. 第三步:在 network 查看详细错误信息 点击红色链接,可 ...
 - socket初步
			
简单demo:https://blog.csdn.net/ns_code/article/details/14105457
 - HDFS(二)
			
HDFS的I/O主要是三个方面: 一致性 HDFS在一致性上面主要是通过校验和(checksum)来实现:从client发起写入的时候会校验一下文件内容,但是发生在pipeline的最后一个节点的时候 ...
 - Spring Boot 入门之持久层篇(三)
			
原文地址:Spring Boot 入门之持久层篇(三) 博客地址:http://www.extlight.com 一.前言 上一篇<Spring Boot 入门之 Web 篇(二)>介绍了 ...
 - Spark性能优化:资源调优篇(转)
			
在开发完Spark作业之后,就该为作业配置合适的资源了.Spark的资源参数,基本都可以在spark-submit命令中作为参数设置.很多Spark初学者,通常不知道该设置哪些必要的参数,以及如何设置 ...
 - input type=number 禁止输入字符“e”的办法
			
输入框input,的type设置为number,本想只输入数字,但是字符“e”却能通过, 首先科普一下, <body> <input onkeypress="getCode ...
 - Python——str常用操作方法
			
1. 索引(即下标) s = 'ABCDEFGHIJKLMN' s1 = s[0] print('s[0] = ' + s1) #s[0] = A print('s[3] = '+ s[3]) #s[ ...
 - python3api-ms-win-crt-runtime-l1-1-0.dll丢失解决方法
			
先记录一个之前遇到的问题: 在安装了pycharm后,发现 通过上网发现,其实就是没有安装pip和setuptools,其实 Python3以后都是默认安装pip的,所以最后的解决办法是将我目前的Py ...