浅谈【多线程与并发】之进程

目录

1、进程

1.1程序的执行方式

1.2进程是个什么东西

1.3进程和程序区别

2、OS为什么要引入进程

2.1进程状态

3、程序执行过程

3.1Linux的进程地址空间的分布

4、Linux下的进程相关的API函数

4.1创建一个新的进程

4.2获取进程id号

4.3进程的退出

4.4等待子进程的结束


谢谢帅气美丽且优秀的你看完我的文章还要点赞、收藏加关注

没错,说的就是你,不用再怀疑!!!

希望我的文章内容能对你有帮助,一起努力吧!!!


1、进程

程序:数据结构+算法

数据结构:用来表示人们思维对象的抽象概念的物理表现叫做:数据。对于数据进行处理操作规则叫 做:指令操作

对某一有限数据集所实施的、目的在与借鉴某一问题的一组有限的指令集合,称为:计算。

计算机就是用指令来处理数据。程序就是数据和指令的集合,一个程序的执行过程就是计算。

1.1程序的执行方式

  • 顺序方式
    • 一个程序完全执行完毕之后才能执行下一个程序
    • 比如:一个程序分为三步骤
      • 输入数据--->计算-->打印结构
    • 缺陷:
      • CPU的利用率非常低
  • 并发执行
    • 把一个取指令的执行过程,分为几个不同步骤
    • 不同步骤由不同的硬件完成,这样可以多个程序同时执行

为了提供CPU的利用率,增加 吞吐量 并发执行 ,现代操作系统特地引入 进程 概念

1.2进程是个什么东西

进程是具有独立功能的程序,关于某个数据集合上的依次运行活动。

1.3进程和程序区别

1. 程序是静态的概念(是指令的有序集合 ,“程序文件”),进程是一个动态概念(动态产生,动态消 亡)

2. 进程是一个程序的一次执行活动,一个程序可以对应多个进程。

3. 进程是一个独立的活动单位,进程的是竞争系统资源的基本单位。

进程和程序的区别,好比 “ 炒菜和菜谱 ” 的区别

2、OS为什么要引入进程

就是为了能够让程序并发执行(同一时间段有多个程序在运行);进程是如何做到让多个程序并发执行 呢?

程序的并发,实际就是进程的并发。进程如何同时运行,如何并发?

2.1进程状态

OS把一个进程的执行过程,分为了几个不同的阶段(状态

  • 创建态:在进程创建的时候,系统会生成一个空白的PCB(proccess control block)进程控制块
  • 就绪态 (Ready):准备工作已经做好了,只要有CPU就可以了。就可以执行了。
  • 运行态 (Running):CPU正在执行这个进程的指令的。
  • 阻塞态 (Blocking,等待waiting):进程正在等待其他的外部事件。
  • 消亡态:会释放,PCB(proccess control block)进程控制块

PCB(proccess control block)进程控制块

进程可以在这些状态下进行切换。

就绪队列 ”:Ready Queue

  • 所处 “ Ready ” 状态的进程,都在一个 “ 后备队列 ”,“ 调度程序 ” 负责确定下一个进入 “ Running ” 状态的进程。

调度策略 ”:调度算法

  • 分时系统:调度策略以 “ 时间片轮转 ” 为主要策略的系统。
    • 时间片轮转 ” :分时,每一个进程执行一段时间(“ 时间片 ”)
    • 如:大部分的桌面系统都是分时系统: linux,android,windows,macos,unix ...
  • 实时系统:调度策略以“ 实时策略 ” 为主要策略的系统
    • 实时策略 ”:每次调度都取优先级最高的那个进程执行,直到这个进程执行完毕或者它主动 放弃CPU再或者其他更高的优先级的进程进行抢占。
    • 如: ucos,freeRTOS...
    • 抢占:插队,“ 强盗逻辑

3、程序执行过程

程序的执行过程:进程的动态生成

执行过程:分配资源----->产生进程---->执行指令...

进程要做的第一件事:就是申请一块内存区域来存储程序的数据,不同的数据属性是不一样,分区域来 存储程序数据的。

3.1Linux的进程地址空间的分布

分段 ”:分不同的逻辑区域

Linux对与进程的数据进行分段管理,不同的属性的数据,存储在不同的“ 内存段 ”中,不同的内存段 (内存区域)的属性和管理方法都是不一样。

  • .txt :文本区
    • 主要存放代码
    • 只读并且共享的,这段内存在程序运行期间(进程存活期间),不会被释放。
    • 代码段”随程序的持续性(随进程的持续性)
  • .data :数据段
    • 主要存放程序的已经初始化的全局变量和已经初始化的 static (静态)变量
    • 可读可写,这段内存在进程运行期间,会一直存在,随进程持续性。
  • .bss :数据段
    • 主要存放程序中没有初始化的全局变量和没有初始化的static变量。
    • 可读可写,这段内存在进程运行期间,会一直存在,随进程持续性。
    • .bss 段,在进程初始化的时候,(可能)会全部初始化为0.
  • .rodata : read only data 只读数据段
    • 主要存放程序中的只读数据(如:字符串常量,整型常量....)。
    • 只读,这段内存在进程运行期间,会一直存在,随进程持续性。
  • stack :栈空间(栈区)
    • 主要存放局部变量(非static变量)
    • 可读可写,这段空间,会自动释放(代码块执行完毕,代码块中的局部变量的空间就释放了) 随代码块持续性。
    • 返回一个局部变量的地址,是有问题的原因就是在于这里。
  • heap :堆空间(堆区)动态内存区域
    • 主要是 malloc/realloc/calloc 等动态分配的空间。
    • 可读可写的,这段内存在进程运行期间,一旦分配,就会一直存在,直到手动释放,或者进程 消亡,
    • 防止 “内存泄漏” / “ 垃圾内存 ” 一定要主要一旦开辟空间,就要收到释放。

使用的内存地址:并不是物理地址,而是虚拟地址(虚拟内存)。

  • 用户内存 (用户态)
  • 内核内存 (内核态)
    • 如:是 4G 内存,其中有一个 1G 是内核内存

4、Linux下的进程相关的API函数

4.1创建一个新的进程

#include <sys/types.h>
#include <unistd.h>
#include <iostream>


int main()
{
    // 父进程创建子进程
    pid_t id = fork();
    if(id == 0)// 子进程,那么将该子进程需要执行的代码写道该if下面就可以了
    {
        for(int i =  0;i < 10;i++)
            std::cout << getpid() << ":" << i << std::endl;
    }

    id = fork();
    if(id == 0)// 子进程,那么将该子进程需要执行的代码写道该if下面就可以了
    {
        for(int i =  10;i < 20;i++)
            std::cout << getpid() << ":" << i << std::endl;
    }

    std::cout << "123456" << std::endl;


    while(1);
    return 0;
}

4.2获取进程id号

获取当前进程 id 号

获取父进程 id 号

4.3进程的退出

进程的退出存在两种情况:

  • 自杀(自己退出)
    • main 函数的返回,进程就会退出
    • 调用进程退出函数

他杀(被操作系统干掉/其他进程干掉)

#include <iostream>
#include <unistd.h>
#include <sys/types.h>

int main()
{
    pid_t pid = fork();
    if(pid == 0)
    {
        for(int i = 0;i < 10;i++)
        {
            if(i == 5)
                _exit(0);
            std::cout << i ;
        }
        std::cout << "儿" << std::endl;
    }
    else
    {
        for(int i = 0;i < 10;i++)
        {
            if(i == 5)
                exit(0);
            std::cout << "父:" << i ;
        }
        std::cout << std::endl;
    }

    return 0;
}

4.4等待子进程的结束

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


int main()
{
    pid_t pid = fork();
   
    if(pid == 0)
    {
        sleep(1);
        for(int i = 0;i < 1000;i++)
            std::cout << i << std::endl;
        
        return 0;
    }
    else
    {
        int status = 0;
        int s_pid = waitpid(-1,&status,0); // 0非阻塞

        std::cout <<"id:" << s_pid << "退出码:" <<status << std::endl;
        if(status == 0)
        {
            std::cout << "程序正常退出" << std::endl;
        }
        else if(status == -1)
        {
            std::cout << "程序因为xxx异常退出" << std::endl;
            // 弹出程序程序的按钮供用户选择/自动重启程序
        }
    }

    return 0;
}

  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值