关于多进程创建,此处只讲解一个函数fork().

1.进程创建

先上代码:

  #include"iostream"
#include<unistd.h> //unix标准文件
int main()
{
using namespace std;
pid_t pid;
cout<<"parent have!"<<endl;
pid = fork();//执行fork的时候到底发生了什么?
if(pid == -)//错误创建
{
perror("fork error");
_exit();
}
else if(pid == )//子进程
{ cout<<"i am child,pid = "<<getpid()<<" my parent is:"<<getppid()<<endl;
}
else//父进程
{
// sleep(1);
cout<<"i am parent,pid = "<<getpid()<<" my parent is:"<<getppid()<<endl;
}
cout<<"both have!"<<endl;
return ;
}

运行结果:

 程序及结果分析:

 程序分析:

pid = fork();//执行fork的时候到底发生了什么?

这行代码到底发生了什么?我们需要清楚:在这行代码执行之前,如果不考虑系统调用这个层次的进程,那么就只有一个进程,就是main函数所在的进程.,程序的逻辑是顺序逻辑.那么这行代码执行后,将会发生什么?

"main"进程将会创建一个子进程,确切的讲是复制一个子进程,也就是fork创建子进程,是基于当前进程,复制了其父进程的用户空间(也就是你所看见的上面的代码全部都会被复制).也就是,此刻,存在了两个并行的进程(这个很重要.并不是我们认为的父进程执行完毕了再执行子进程).更确切的讲,下一个时刻,父进程要执行上述代码中的8行以后的代码,子进程也要执行8行以后的代码,究竟谁先执行,看谁抢到了CPU.

上述程序中,根据fork的返回值,来确定即将要执行什么.从形式上看,明显感觉到fork()的返回值并不是一个值,而是>0的值和等于0的值?难道一个函数可以返回两个返回值?也显然不是,是因为父进程创建了子进程,子进程既然复制了父进程的用户空间,自然来看,有两个pid.执行fork()函数后,父进程的pid为子进程的ID端口号,子进程的pid是0.所以才会根据pid的差异执行不同的动作.

 结果分析:

从结果可以看到,"parent have!"仅仅打印了一次,而"both have!"执行了两次.这是因为,fork创建的子进程不会执行在此之前的程序,只会执行fork()之后的,而"both have!"并没有限定其为子进程还是父进程需要执行的.

从结果中可以看出:父进程的部分先得到执行,表明父进程可能先得到返回值,先抢占到cpu(注意这里只是说可能).而且,父进程和子进程的内容均得到了显示(如果是我们单进程的程序,if 和else if 不可能同时执行).

2.创建多个子进程

  #include"iostream"
#include<unistd.h>
int main()
{
using namespace std;
pid_t pid;
cout<<"parent have!"<<endl;
for(int i = ;i < ;i++)
{
pid = fork();//执行fork的时候到底发生了什么?
if(pid == )
{
// cout<<"the ID of son "<<i+1<<":"<<getpid()<<endl;
break;//这个很重要,思考为什么
}
} if(pid == -)//错误创建
{
perror("fork error");
_exit();
}
else if(pid == )//子进程
{
//sleep(1);
cout<<"i am child,pid = "<<getpid()<<" my parent is:"<<getppid()<<endl;
}
else//父进程
{
sleep();
cout<<"i am parent,pid = "<<getpid()<<" my parent is:"<<getppid()<<endl;
}
cout<<"both have!"<<endl;
return ;
}

程序运行结果:

 程序及结果分析:

 程序分析:

假如我们现在想一个父进程创建多个子进程,比如创建5个子进程.我们应该怎么做?

     for(int i = ;i < ;i++)
{
pid = fork();//执行fork的时候到底发生了什么?
if(pid == )
{
// cout<<"the ID of son "<<i+1<<":"<<getpid()<<endl;
break;//结束该子进程
}
}

注意:为什么要在for循环里加了条件判断和break,不加会发生什么?

我们需要注意的是:我们的父进程创建了子进程之后,子进程和父进程拥有完全一样的用户代码,也就意味着,如果我们不加if判断,那么我们的子进程也将成为新的父进程,创建新的子进程,也就是,每执行一次循环,之前创建的子进程都会成为子进程,也就会会造成指数级增长,最终进程会变成2^5-1个,共31个.当加了break之后呢?当父进程创建完子进程之后,我们说过子进程返回的pid为0,此时,会跳出循环体,阻止了fork()的执行,也就阻止了子进程创建新的子进程(但并不影响子进程执行下面的内容,只是不执行fork而已).而父进程由于得到的是子进程的ID,从而可以继续执行循环体.而新创建的子进程自然也不能执行循环体,这样下来,一个父进程创建了5个等级一样的子进程.

父子进程共享

共享遵循的原则:读时共享写时复制原则.

针对前文中:父进程创建子进程的例子,我们会产生这样的疑问?子进程是完完全全copy父进程的内容吗?  至少现在的Linux系统不是.如果某个变量在子进程是被读的,而不是写的,那么这个变量物理地址空间就是被共享的(注意并不是逻辑空间).如果在子进程中要被修改,那么就会产生一般性的复制行为.

我们还是需要清楚:父子进程的用户空间基本是完全一样的,但是关于PCB这一块的内核空间并不相同,毕竟每个进程的ID都不同.

c++并发编程之进程创建(给那些想知道细节的人)的更多相关文章

  1. 并发编程 ~~~ 多进程~~~进程创建的两种方式, 进程pid, 验证进程之间的空间隔离, 进程对象join方法, 进程对象其他属性

    一 进程创建的两种方式 from multiprocessing import Process import time def task(name): print(f'{name} is runnin ...

  2. Java并发编程:进程的创建

    Java并发编程:进程的创建 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...

  3. Java并发编程:如何创建线程?

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  4. 【转】Java并发编程:如何创建线程?

    一.Java中关于应用程序和进程相关的概念 在Java中,一个应用程序对应着一个JVM实例(也有地方称为JVM进程),一般来说名字默认是java.exe或者javaw.exe(windows下可以通过 ...

  5. python并发编程之进程、线程、协程的调度原理(六)

    进程.线程和协程的调度和运行原理总结. 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asynci ...

  6. 2、Java并发编程:如何创建线程

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  7. Python之路(第三十七篇)并发编程:进程、multiprocess模块、创建进程方式、join()、守护进程

    一.在python程序中的进程操作 之前已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起来的python程序 ...

  8. 35 - 并发编程-GIL-多进程

    目录 1 GIL 1.1 为什么会有GIL 1.2 GIL与thread lock 1.3 个人总结 2 multiprocessing模块 2.1 Process类 2.2 Process类的方法 ...

  9. 网络编程基础----并发编程 ---守护进程----同步锁 lock-----IPC机制----生产者消费者模型

    1  守护进程: 主进程 创建 守护进程   辅助主进程的运行 设置进程的 daemon属性 p1.daemon=True 1 守护进程会在主进程代码执行结束后就终止: 2 守护进程内无法再开启子进程 ...

随机推荐

  1. centos7中搭建ftp服务

    博客搬家: centos7中搭建ftp服务 最近想和同学共享一些文件资源,于是在实验室服务器上搭建个ftp服务,本博客记录一下配置的流程.过程基本是参照别人的方法来做的,博客也是在别人博客基础上修改的 ...

  2. LeetCode 343.整数拆分 - JavaScript

    题目描述:给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 题目分析 题目中"n 至少可以拆分为两个正整数的和",这个条件说 ...

  3. 青石巷-小L的爸爸

    小L有一个和谐的家. 爸爸具体职业不明,在统战部工作,刚开始和妈妈在一起工作. 妈妈是个会跳舞的语文老师. 奶奶之前也是个老师. 爷爷是个建筑师. 爸爸是最有文采的一个.在小L看来,他的一言一行,一举 ...

  4. 打包 压缩 命令tar zip

    tar语法 #压缩tar -czvf ***.tar.gztar -cjvf ***.tar.bz2#解压缩tar -xzvf ***.tar.gztar -xjvf ***.tar.bz2 tar ...

  5. zabbix-proxy配置文件参数说明

    配置文件路径: /etc/zabbix/zabbix_proxy.conf Server=10.0.0.10 #<===指定zabbix server的ip地址或主机名 Hostname=zab ...

  6. Go语言基础之结构体(面向对象编程上)

    1 自定义类型和类型别名 1.1 自定义类型 Go语言中可以基于一些基本的数据类型,使用type关键字定义自定义类型的数据 . 自定义类型定义了一个全新的类型,该新类型具有基本数据类型的特性.自定义类 ...

  7. 前端开发:这10个Chrome扩展你不得不知

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://blog.bitsrc.io/10-top-chrome-extensions-f ...

  8. Win10的Python3.8升级与安装

    一.前言 1.说明 博主电脑Python3.6用了有3年多了,正好疫情期间有时间,给更新到3.8版本,边安装边记录下安装流程,希望对读者有帮助 2.系统环境 联想电脑,系统Win10,上一个Pytho ...

  9. 简单了解css3样式表写法和优先级

    css3和css有什么区别?首先css3是css(层叠样式表)技术的升级版本,而css是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言. ...

  10. 微信小程序入门笔记-账号注册(1)

    小程序注册 微信小程序开发之前,必须先有小程序账号,下面是注册步骤: 1.打开网页 微信公众平台https://mp.weixin.qq.com/,点击立即注册按钮 2.注册类型 选择小程序开发 3. ...