本文内容:

1.进程的结构

2.程序转化为进程的过程

3.进程的创建

4.进程的结束

背景知识:

1.进程是计算机中处于运行的程序的实体

2.进程是线程的容器

3.程序本身只是指令,数据以及组织形式的描述,进程才是程序真正的运行实例

4.多个进程可以与同一个程序关联,而每个进程则是以同步或者异步的方式独立运行

一.Linux的进程结构

Linux进程结构由三部分组成:代码段,数据段,堆栈段

代码段:存放程序代码,如果多个进程运行同一个程序则他们使用同一个代码段

数据段:存放程序的全局变量,常量,静态变量

堆栈段:函数的参数,函数内部定义的局部变量,进程控制块PCB(处于进程核心堆栈的底部)

ps:

1.PCB是进程存在的唯一标识,系统通过PCB的存在而感知进程的存在

2.系统通过PCB对进程进行调度和管理,PCB包括创建进程,执行程序,退出进程以及改变进程优先级等

3.进程与PID进程标识符是一对一关系,而与程序文件之间是多对一关系!

二.程序转化为进程过程

Linux程序的生成分为四个阶段:预编译,编译,汇编,链接

ps:编译器G++经过预编译,编译,汇编三个步骤将源程序文件转化为目标文件,如果程序有多个目标文件或者程序使用了库函数,则编译器还需要将所有的目标wen就链接起来,最后形成可执行程序

程序转换为进程的步骤:

1)内核将程序代码和数据读入内存,为程序分配内存空间

2)内核为进程分配进程标识符PID和其他资源

3)内核为进程保存PID以及相应的状态信息,把进程放到运行队列中等待执行,程序转化为进程后就可以被操作系统的调度程序调度执行了

三.进程的创建

背景知识:

1.进程创建有两种方式:由操作系统创建,由父进程创建

2.系统启动时,操作系统会创建一些进程,他们承担着管理和分配系统资源的任务,这些进程通常被叫做系统进程

3.系统允许一个进程创建子进程,从而形成进程树结构

4.整个Linux系统的所有进程也是一个树形结构、

5.除了0号进程是由系统创建的,其他进程都是由他们的父进程创建的

关于进程的创建函数fork:

pid_t fork(void)

1.对于父进程,fork函数返回子进程的PID

2.对于子进程,fork函数返回0

3.如果创建出错,则fork函数返回-1

函数分析:fork函数创建一个新进程,并从内核中为进程分配一个新的可用的进程标识符PID,然后将父进程空间中的内核复制到子进程,包括父进程的数据段和堆栈段,和父进程共享代码段,这个时候子进程和父进程一模一样!

问题:为什么对于不同的进程(父进程,子进程),fork函数的返回值会不一样呢?

因为在复制时复制了进程的堆栈段,所以两个进程都停留在fork函数中,等待返回,因此fork函数会返回两次,为了方便区别父进程和子进程,所以返回值不一样


fork函数样例:

#include <iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
using namespace std; int main()
{
pid_t pid;
pid=fork();
if(pid<0)
{
cout<<"fork error"<<endl;
exit(-1);//abnormal exit
}
else if(pid==0)
{
cout<<"son process,son:"<<getpid()<<",parent:"<<getppid()<<endl;
}
else
{
cout<<"parent process,parent:"<<getpid()<<"son:"<<pid<<endl;
sleep(2);
}
return 0;
}

分析:getpid为获得当前进程的pid,getppid为获得当前进程的父进程的pid,上述代码验证了fork的不同返回值

下面我们验证一下父进程和子进程只共享了代码段,而没有共享数据段和堆栈段

#include <iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
using namespace std; int data_x=1; int main()
{
pid_t pid;
int stack_x=1;
int *heap=(int*)malloc(sizeof(int));
*heap=3; pid=fork(); if(pid<0)
{
cout<<"fork error"<<endl;
exit(-1);
}else if(pid==0)
{
data_x++;
stack_x++;
(*heap)++;
cout<<"son,data_x="<<data_x<<",stack_x="<<stack_x<<",heap="<<*heap<<endl;
exit(0);
}else
{
sleep(2);
cout<<"parent,data_x="<<data_x<<",stack_x="<<stack_x<<",heap="<<*heap<<endl;
}
return 0;
}

分析:我们发现数据段,栈中,堆中的数据,两个进程的这些数据都是不一样的,证明父进程和子进程没有共享数据段和堆栈段!,对子进程中数据段和堆栈段中内容的修改,并不会影响父进程中的数据,父子进程共享代码段的目的是节省存储空间

父进程的资源大部分被子进程复制,只有小部分是不同的,比如pid,该进程的父进程号等这些东西

关于“写时复制”概念的说明:

现在的Linux内核在实现fork函数时往往在创建子进程时并不立即复制父进程的数据段和堆栈段,而是当子进程修改这些数据内容时复制操作才会发生,内核才会给子进程分配进程空间,将父进程的内容复制过来,然后继续后面的操作,这样的实现对一些为了复制自身完成一些工作的进程来说更为合理!,效率也更高

四.进程的结束:

Linux中分为进程正常退出和进程异常退出

1)正常退出的方式:main函数中return 0,调用exit函数,调用_exit函数

2)异常退出的方式:调用abort函数,进程收到某个信号而该信号会使进程终止

当然,不管哪一种方式,系统最终都会执行一段相同的代码:用来关闭进程打开的文件描述符,释放其锁占用的内存资源

需要区别的是,return之后控制器交给了调用函数,而exit是个函数,执行完后系统的控制权交给了系统

现在我们再来看一下_exit函数和exit函数:

_exit函数更为接近底层,exit函数是_exit函数的一个封装,那么exit函数比 _exit函数多做了什么事情呢?

exit函数会进行【读完/写完缓存IO】的操作,而_exit函数则不会,在不恰当的时候使用_exit函数无法保证数据的完整性!

换句话说就是,exit函数在彻底结束进程之前会检查文件的打开情况,把文件缓冲区的内容写回文件!

那调用_exit函数为什么会出现数据不完整的情况呢?我们深究一下Linux底层

在Linux标准函数库中,有一种被称为【缓冲IO】的操作,其特征就是对应每一个打开的文件,在内存中都有一片缓冲区,每次读文件时会连续的读出若干条数据,这样在下次读数时就可以直接从内存的缓冲区中读取,提高了速度,同样的,每次写文件的时候也仅仅是写入内存缓冲区,等满足一定的条件后(积累到一定数量的字符),再将缓冲区中的内容一次性写入文件,这种技术大大增加了文件的读写速度,但是也给编程增添了一点小坑,比如有一些数据,理论上应该写入了文件,但实际上因为没有满足特定的条件,它还知识保存是内存的缓冲区中,如果采用_exit函数直接结束进程,缓冲区的数据就会丢失,因此想要保证数据的完整性,就一定要使用exit函数,而不是_exit函数

【Linux】进程的结构,创建,结束,以及程序转化为的进程的过程的更多相关文章

  1. 如何在 Azure 中均衡 Linux 虚拟机负载以创建高可用性应用程序

    负载均衡通过将传入请求分布到多个虚拟机来提供更高级别的可用性. 本教程介绍了 Azure 负载均衡器的不同组件,这些组件用于分发流量和提供高可用性. 你将学习如何执行以下操作: 创建 Azure 负载 ...

  2. Linux进程理解与实践(五)细谈守护进程

    一. 守护进程及其特性      守护进程最重要的特性是后台运行.在这一点上DOS下的常驻内存程序TSR与之相似.其次,守护进程必须与其运行前的环境隔离开来.这些环境包括未关闭的文件描述符,控制终端, ...

  3. {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll

    Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...

  4. ASP.NET Core Linux下为 dotnet 创建守护进程(必备知识)

    前言 在上篇文章中介绍了如何在 Docker 容器中部署我们的 asp.net core 应用程序,本篇主要是怎么样为我们在 Linux 或者 macOs 中部署的 dotnet 程序创建一个守护进程 ...

  5. Linux内核分析——进程描述与创建

    20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验内容 ...

  6. ASP.ENT Core Linux 下 为 donet创建守护进程(转载)

    原文地址:http://www.cnblogs.com/savorboard/p/dotnetcore-supervisor.html 前言 在上篇文章中介绍了如何在 Docker 容器中部署我们的 ...

  7. Java实现Linux下服务器程序的双守护进程

    作者:Vinkn 来自http://www.cnblogs.com/Vinkn/ 一.简介 现在的服务器端程序很多都是基于Java开发,针对于Java开发的Socket程序,这样的服务器端上线后出现问 ...

  8. Linux进程: task_struct结构体成员

    一:简介 为了管理进程,内核必须对每个进程所做的事情进行清除的描叙. 比如:内核必须知道进程优先级,他是正在CPU上运行还是因为某些事件被阻塞了,给它分配了什么样的地址空间,允许它访问哪个文件等等.这 ...

  9. 关于linux的一点好奇心(五):进程线程的创建

    一直以来,进程和线程的区别,这种问题一般会被面试官拿来考考面试者,可见这事就不太简单.简单说一点差异是,进程拥有独立的内存资源信息,而线程则共享父进程的资源信息.也就是说线程不拥有内存资源,所以对系统 ...

随机推荐

  1. MyBatis框架的搭建

    前言:MyBatis框架的前身是iBatis,本身是Apache的一个开源项目. MyBatis框架是一个半自动的orm映射框架,是实体类和sql语句之间建立映射关系,sql语句写在单独的配置文件中, ...

  2. hdu6172&&hdu6185&&P5487——BM算法

    hdu6172 模板的简单应用 先根据题中的表达式求出前几项,再上BM,注意一下n的大小关系. #include <bits/stdc++.h> using namespace std; ...

  3. Apache Shiro<=1.2.4反序列化RCE漏洞

    介绍:Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 漏洞原因:因为shiro对cookie里的rememberme字段进行了反序列化,所以如果知道了 ...

  4. 《vue》实现动态显示与隐藏底部导航方法!

    在日常项目中,总有几个页面是要用到底部导航的,总有那么些个页面,是不需要底部导航的,这里列举一下页面底部导航的显示与隐藏的两种方式: 其实很简单,我们在路由里面带上参数,这个参数就用来区分那个页面显示 ...

  5. dbt 集成presto试用

    dbt 团队提供了presto 的adapter同时也是一个不错的的参考实现,可以学习 当前dbt presto 对于版本的要求是0.13.1 对于当前最新版本的还不支持,同时需要使用源码安装pip ...

  6. pyqt5 + pyinstaller 制作爬虫小程序

    环境:mac python3.7 pyqt5 pyinstaller ps: 主要是熟悉pyqt5, 加入了单选框 输入框 文本框 文件夹选择框及日历下拉框 效果图: pyqt5 主程序文件 # -* ...

  7. c博客06-结构

    1.本章学习总结(2分) 1.1 学习内容总结 结构体如何定义.成员如何赋值 结构体数组排序做法 结构体指针怎么用 共用体.枚举类型做法 文件读写,文件中数据如何读进结构体数组 1.2 本章学习体会 ...

  8. 微信小程序之使用wx:for遍历循环

    效果图如下: 实现代码如下:type.js: // pages/type/type.js Page({ /** * 页面的初始数据 */ data: { types: "" }, ...

  9. 2019_软工实践_Beta(4/5)

    队名:955 组长博客:点这里! 作业博客:点这里! 组员情况 组员1(组长):庄锡荣 过去两天完成了哪些任务 文字/口头描述 ? 测试新功能中 展示GitHub当日代码/文档签入记录 接下来的计划 ...

  10. [转] cmake源码编译安装jsoncpp

    1.下载jsoncpp源码 wget https://github.com/open-source-parsers/jsoncpp/archive/master.zip 2.解压缩源码文件 unzip ...