linux创建新进程就分配空间,linux几种创建进程的方法

在Linux中主要提供了fork、vfork、clone三个进程创建方法。

在linux源码中这三个调用的执行过程是执行fork(),vfork(),clone()时,通过一个系统调用表映射到sys_fork(),sys_vfork(),sys_clone(),再在这三个函数中去调用do_fork()去做具体的创建进程工作。

fork

fork创建一个进程时,子进程只是完全复制父进程的资源,复制出来的子进程有自己的task_struct结构和pid,但却复制父进程其它所有的资源。例如,要是父进程打开了五个文件,那么子进程也有五个打开的文件,而且这些文件的当前读写指针也停在相同的地方。所以,这一步所做的是复制。这样得到的子进程独立于父进程,

具有良好的并发性,但是二者之间的通讯需要通过专门的通讯机制,如:pipe,共享内存等机制, 另外通过fork创建子进程,需要将上面描述的每种资源都复制一个副本。这样看来,fork是一个开销十分大的系统调用,这些开销并不是所有的情况下都是必须的,比如某进程fork出一个子进程后,其子进程仅仅是为了调用exec执行另一个可执行文件,那么在fork过程中对于虚存空间的复制将是一个多余的过程。但由于现在Linux中是采取了copy-on-write(COW写时复制)技术,为了降低开销,fork最初并不会真的产生两个不同的拷贝,因为在那个时候,大量的数据其实完全是一样的。写时复制是在推迟真正的数据拷贝。若后来确实发生了写入,那意味着parent和child的数据不一致了,于是产生复制动作,每个进程拿到属于自己的那一份,这样就可以降低系统调用的开销。所以有了写时复制后呢,vfork其实现意义就不大了。

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

在fork之后,子进程和父进程都会继续执行fork调用之后的指令。子进程是父进程的副本。它将获得父进程的数据空间,堆和栈的副本,这些都是副本,父子进程并不共享这部分的内存。也就是说,子进程对父进程中的同名变量进行修改并不会影响其在父进程中的值。但是父子进程又共享一些东西,简单说来就是程序的正文段。正文段存放着由cpu执行的机器指令,通常是read-only的。下面是一个验证的例子:

例1:fork.c

#include

#include

#include

#include

int main()

{

int a = 5;

int b = 2;

pid_t pid;

pid = fork();

if(pid == 0) {

a = a-4;

printf("I'm a child process with PID [%d],the value of a: %d,the value of b:%d.\n",pid,a,b);

}else if(pid < 0) {

perror("fork");

}else {

printf("I'm a parent process, with PID [%d], the value of a: %d, the value of b:%d.\n", pid, a, b);

}

return 0;

}

#gcc –o fork fork.c

#./fork

运行结果:

I’m a child process with PID[0],the value of a:1,the value of b:2.

I’m a parent process with PID[19824],the value of a:5,the value of b:2.

可见,子进程中将变量a的值改为1,而父进程中则保持不变。

vfork

vfork系统调用不同于fork,用vfork创建的子进程与父进程共享地址空间,也就是说子进程完全运行在父进程的地址空间上,如果这时子进程修改了某个变量,这将影响到父进程。

因此,上面的例子如果改用vfork()的话,那么两次打印a,b的值是相同的,所在地址也是相同的。

但此处有一点要注意的是用vfork()创建的子进程必须显示调用exit()来结束,否则子进程将不能结束,而fork()则不存在这个情况。

Vfork也是在父进程中返回子进程的进程号,在子进程中返回0。

用 vfork创建子进程后,父进程会被阻塞直到子进程调用exec(exec,将一个新的可执行文件载入到地址空间并执行之。)或exit。vfork的好处是在子进程被创建后往往仅仅是为了调用exec执行另一个程序,因为它就不会对父进程的地址空间有任何引用,所以对地址空间的复制是多余的 ,因此通过vfork共享内存可以减少不必要的开销。下面这个例子可以验证子进程调用exec时父进程是否真的已经结束阻塞:

例2:execl.c

#include

#include

#include

#include

#include

#include

#include

int main()

{

int a = 1;

int b = 2;

pid_t pid;

int status;

pid = vfork();

if(pid == -1) {

perror("Fork failed to creat a process");

exit(1);

}

else if(pid == 0)

{

// sleep(3);

if(execl("/bin/example","example",NULL)<0)

{

perror("Exec failed");

exit(1);

}

exit(0);

// }else // if(pid != wait(&status)) {

// perror("A Signal occured before the child exited"); }

else

printf("parent process,the value of a :%d, b:%d, addr of a: %p,b: %p\n",a,b,&a,&b); exit(0); }

Example.c

#include

int main()

{

int a = 1;

int b = 2;

sleep(3);

printf("Child process,the value of a is %d,b is %d,the address a %p,b %p\n",a,b,&a,&b);

return 0;

}

#gcc –o execl execl.c #./ execl 运行结果:

Child process ,The value of a is 1,b is 2,the address a 0xbfb73d90,b 0xbfb73d8c

如果将注释掉的三行加入程序的话,由于父进程wait()而阻塞,因此即使此时子进程阻塞,父进程也得不到运行,因此运行结果如下:

The value of a is 1,b is 2,the address a 0xbfb73d90,b 0xbfb73d8c

Parent process,the value of a:1,b:2,addr ofa:0xbfaa710c, b:0xbf aa7108

另外还应注意的是在它调用exec后父进程才可能调度运行,因此sleep(3)函数必须放在example程序中才能生效。

clone

系统调用fork()和vfork()是无参数的,而clone()则带有参数。fork()是全部复制,vfork()是共享内存,而clone() 是则可以将父进程资源有选择地复制给子进程,而没有复制的数据结构则通过指针的复制让子进程共享,具体要复制哪些资源给子进程,由参数列表中的 clone_flags来决定。另外,clone()返回的是子进程的pid。下面来看一个例子:

例3:clone.c

#include

#include

#include

#include

#include

#include

#include

int variable,fd;

int do_something() {

variable = 42;

printf("in child process\n");

close(fd);

// _exit(0);

return 0;

}

int main(int argc, char *argv[]) {

void *child_stack;

char tempch;

variable = 9;

fd = open("/test.txt",O_RDONLY);

child_stack = (void *)malloc(16384);

printf("The variable was %d\n",variable);

clone(do_something, child_stack+10000, CLONE_VM |CLONE_FILES,NULL);

sleep(3); /* 延时以便子进程完成关闭文件操作、修改变量 */

printf("The variable is now %d\n",variable);

if(read(fd,&tempch,1) < 1) {

perror("File Read Error");

exit(1);

}

printf("We could read from the file\n");

return 0;

}

#gcc –o clone clone.c

#./clone

运行结果:

the value was 9

in child process

The variable is now 42

File Read Error

从程序的输出结果可以看出:

子进程将文件关闭并将变量修改(调用clone时用到的CLONE_VM、CLONE_FILES标志将使得变量和文件描述符表被共享),父进程随即就感觉到了,这就是clone的特点。由于此处没有设置标志CLONE_VFORK,因此子进程在运行时父进程也不会阻塞,两者同时运行。

总结

一、fork

1. 调用方法

#include

#include

pid_t fork(void);

正确返回:在父进程中返回子进程的进程号,在子进程中返回0

错误返回:-1

2. fork函数调用的用途

一个进程希望复制自身,从而父子进程能同时执行不同段的代码。

二、vfork

1. 调用方法

与fork函数完全相同

#include

#include

pid_t vfork(void);

正确返回:在父进程中返回子进程的进程号,在子进程中返回0

错误返回:-1

2. vfork函数调用的用途

用vfork创建的进程主要目的是用exec函数执行另外的程序。

三、clone

1.调用方法

#include

int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);

正确返回:返回所创建进程的PID,函数中的flags标志用于设置创建子进程时的相关选项,具体含义参看P25

错误返回:-1

2.clone()函数调用的用途

用于有选择地设置父子进程之间需共享的资源

四、fork,vfork,clone的区别

1. fork出来的子进程是父进程的一个拷贝,即,子进程从父进程得到了数据段和堆栈段的拷贝,这些需要分配新的内存;而对于只读的代码段,通常使用共享内存的方式访问;而vfork则是子进程与父进程共享内存空间, 子进程对虚拟地址空间任何数据的修改同样为父进程所见;clone则由用户通过参clone_flags

的设置来决定哪些资源共享,哪些资源拷贝。

2. fork不对父子进程的执行次序进行任何限制,fork返回后,子进程和父进程都从调用fork函数的下一条语句开始行,但父子进程运行顺序是不定的,它取决于内核的调度算法;而在vfork调用中,子进程先运行,父进程挂起,直到子进程调用了exec或exit之后,父子进程的执行次序才不再有限制;clone中由标志CLONE_VFORK来决定子进程在执行时父进程是阻塞还是运行,若没有设置该标志,则父子进程同时运行,设置了该标志,则父进程挂起,直到子进程结束为止。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java文件下载至linux乱码,JAVA 文件下载乱码问题解决办法

页面设置隐藏的iframe页面下载按钮id"btnDown" href"javascript:void(download(btnDown))" >下载模板页面JS脚本function download(id){$("#reqFrame").attr("src",encodeURI("/servlet/Common?actiondownloadByPath&fil…

强行更改linux服务器时间,加强Linux服务器安全的20项建议

一般情况下用 Linux 做桌面在默认配置下是很安全的&#xff0c;我在一定程度上同意这个说法(很值得商榷的话题)。不过 Linux 内置的安全模型和工具做得确实很到位&#xff0c;用户只需进行简单的调整和自定义就可以加强 Linux 服务器安全。与恶意用户做斗争对于所有 Linux 系统…

webshell提权教程linux,Linux下WEBSHELL提权

用phpshell2.0和Linux Kernel2.6x 本地溢出代码配合提ROOT,现在不少LINUX主机都还有这个本地溢出漏洞。前提&#xff1a;1、目标机上安装了GCC能编译源码2、Kernel 2.6.x (> 2.6.13 && < 2.6.17.4)因为是在webshell里溢出成功也得不到返回的ROOT SHELL,所…

Linux宏定义实现类成员函数,全面解析Linux内核的同步与互斥机制

http://blog.csdn.net/sailor_8318/archive/2008/06/30/2599357.aspx【摘要】本文分析了内核的同步及互斥的几种机制&#xff1a;原子运算符(atomicoperator)、自旋锁Spinlock、等待队列Waitqueue、事件Event、completion、信号量Semaphore及其优化版互斥锁&#xff0c;详细分析…

Linux命令sngre,linux gre隧道创建

linux gre隧道创建实验环境两台可以相互通信的虚拟机&#xff0c;两个虚拟机在不通的网段。如下所示host A:[[email protected] ~]# ip a1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127…

linux终端提示符含义,Linux:终端提示符 (prompt) 不如期生效原因

前言先来简单介绍下, prompt是什么鬼? 顾名思义就是提示符的意思, 看起来和我们遥远, 但实际上只要是每个接触shell的童鞋, 都有看到, 那就是我们在输命令时前面的那串提示符.例如:当然, 这个样式是可以修改的, 这就涉及到我们的PS1和PS2了, 有经验或者以前有设置过的童鞋估计…

skyeye linux qt,ARM仿真器SkyEye的安装及使用

SkyEye是一个开源软件(OpenSource Software)项目&#xff0c;中文名字是"天目"。SkyEye的目标是在通用的Linux和Windows平台上实现一个纯软件集成开发环境&#xff0c;模拟常见的嵌入式系统&#xff0c;可在SkyEye上运行μCLinux以及μC/OS-II等&#xff0c;以及各种…

Linux 读写 优化 ssd,linux ssd 优化

一、修改默认的固态硬盘(SSD)柱面大小提升Linux下固态硬盘的使用率&#xff0c;在安装Linux操作系统前就应该做相关工作。系统会先在磁盘上创建分区&#xff0c;通常创建的分区包含固定数量的柱面&#xff0c;而默认情况下&#xff0c;每个柱面由16065512个字节的扇区组成。现在…

linux中dev目录的作用,Linux 的dev目录详解和Linux系统各个目录的作用

Linux /dev目录详解在linux下&#xff0c;/dev目录是很重要的&#xff0c;各种设备都在下面。下面简单总结一下&#xff1a; dev是设备(device)的英文缩写。/dev这个目录对所有的用户都十分重要。因为在这个目录中包含了所有Linux系统中使用的外部设备。但是这里并不是放的外部…

linux 类型排序,Linux命令之排序命令sort使用实例

名称&#xff1a;sort位置&#xff1a;/usr/bin/sort权限&#xff1a;所有用户用法&#xff1a; sort [OPTION]... [FILE]...sort [OPTION]... --files0-fromF选项&#xff1a;-b --ignore-leading-blanks 忽略最前面的空格-f --ignore-case fold lower case to…

2g 双核电脑 linux,9208)(奔腾双核E5200/2G/320G)电脑详细技术

处理器型&#xff1a;intel 酷睿2双核 p7350 intel 酷睿2双核 p7450 intel 酷睿2双核 t6600 intel 奔腾双核t4300 intel 奔腾双核 t4400 intel 赛扬双核 t1600 intel 赛扬双核 t3000操作系统&#xff1a;windowsvista home basic dos标配内存&#xff1a;1gb 2gb 硬盘容量&…

linux shell 高级编程,shell高级编程

条件选择if语句选择执行&#xff1a; 注意&#xff1a;if语句可嵌套单分支if 判断条件;then条件为真的分支代码fi双分支if 判断条件; then条件为真的分支代码else条件为假的分支代码fi多分支if 判断条件1; then条件为真的分支代码elif 判断条件2; then条件为真的分支代码elif 判…

linux menuconfig usb,[Linux]make menuconfig里面的选项很重要

最近在用USB摄像头&#xff0c;发现驱动正常加载&#xff0c;插上USB摄像头&#xff0c;内核设备总是无法加载摄像头的驱动&#xff0c;也没有vidoe0设备&#xff0c;但我以前在2410上是可以的。如下&#xff1a;/ # usb 1-1: new full speed USB device using s1r72v27 and ad…

linux apache 大文件,Apache下error.log文件太大的处理方法

Apache下error.log文件太大的处理方法2019年05月03日| 萬仟网网络运营| 我要评论清除error.log、access.log并限制apache日志文件大小的方法 有个客户反映vps网站打不开&#xff0c;登录系统检查下&#xff0c;客户是win2003系统&#xff0c;发现放置网站文件的清除error.log、…

c语言程序设计臧,清华大学出版社-图书详情-《C程序设计基础(第2版)》

前言C语言是在由UNIX的研制者(美国贝尔实验室的Dennis Ritchie和Ken Thompson)于1970年研制出的B语言的基础上发展和完善起来的。1972年&#xff0c;在DEC PDP-11计算机上实现了最初的C语言&#xff0c;此后C语言伴随着计算机的发展一直走到了今天。C语言是一种支持过程化的、实…

c语言程序设计实践课选题,c语言程序设计实践实验题目

c语言程序设计实践实验题目 绥化学院程序设计实践实验报告范例 参考1实验题目&#xff1a;循环结构程序设计实验目的&#xff1a;1.熟悉 VC6.0 的运行环境&#xff0c;掌握 C 程序的执行方法&#xff1b;2.掌握三种基本数据类型、部分运算符号和常用函数&#xff1b;3.掌握三种…

c语言上机指导答案清华,第一章自测练习答案清华大学c语言习题实验指导及课程设计...

第一章自测练习答案清华大学c语言习题实验指导及课程设计 第一章 自测练习参考答案 一&#xff0e;简答题 1&#xff0e;源程序是程序员创建的&#xff0c;目标程序是编译器创建的&#xff0c;可执行程序是连接器创建的。 2&#xff0e;步骤如下&#xff1a;1)说明程序需求&…

c语言生成随机的坐标,C语言文件的随机读写

前面介绍的文件读写函数都是顺序读写&#xff0c;即读写文件只能从头开始&#xff0c;依次读写各个数据。但在实际开发中经常需要读写文件的中间部分&#xff0c;要解决这个问题&#xff0c;就得先移动文件内部的位置指针&#xff0c;再进行读写。这种读写方式称为随机读写&…

c语言 画线函数,c语言绘制函数曲线

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼我这种方法为什么图形只能显示一下就不见了&#xff0c;这是为什么&#xff1f;能不能用在双曲线上&#xff1f;&#xff1f;能的话改哪里&#xff1f;&#xff1f;#include#includefloat a,b,c,xmin,xmax,max; void menu(){printf…

k6前级效果器怎么用_新手学习电吉他,效果器应选择单块还是综合?

作为一个新手来说&#xff0c;我建议一开始先选择综合型效果器。这里我们先简单介绍下综合效果器与单块效果器。综合效果器可以理解为多个单块的综合体&#xff0c;即包含了很多种效果。一块大综合效果器可能就有三四十种预置音色&#xff0c;有过载、失真、法滋、延迟、混响、…