进程概念

2023-11-14

基本概念:

  • 进程是程序的一个执行实例;
  • 从内核来看,进程是担当分配系统资源的实体。        

注:在Linux操作系统中,大多数指令都是创建了一个个的进程。


操做系统如何管理内存?

答: 使用一个结构体(PCB)来描述进程;

       使用高效的数据结构来组织进程。


描述进程--PCB(process control block):

    进程的信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。这个数据结构在Linux操作系统中被叫做task_struct。

    存放进task_struct结构体中的信息有:

  • 标识符:用来区别其他进程的唯一标识符;
  • 状态:任务的状态,退出代码,退出信号等;
  • 优先级:相对于其它进程的优先级;
  • 内存指针:是用来存放代码和数据的地址,还有其他进程共享的内存块的指针;
  • 程序计数器:程序中即将被执行的下一条指令的地址;
  • 上下文:进程执行时寄存器中的数据(保护现场,进程切换后,切换回来的时候方便恢复到切换时的进程执行的状态);
  • I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表;
  • 记账信息:可能包括处理器的时间总和,使用的时钟数总和,时间限制和记账号等。
  • 其它信息。

组织进程:

    使用一个代替头结点的带环的双向链表来组织进程。

    创建一个进程的本质是:创建一个task_struct结构体,并将该结构体进行初始化插入上面说的带头结点的双向带环链表。

查看进程:

  • 可以通过系统文件夹(/proc)查看


  • 若要查看pid为1的进程,需要查看/proc/1文件夹


  • 大多数进程可以使用top、ps等工具获取

ps aux(查看所有进程)


ps aux | grep hello (用ps aux的输出来作为grep的输入)

  int main()                                                                                                                         
  {
      while(1)
      {
          sleep(1);
      }   
      return 0;
  }   

通过系统调用获取进程标识符(PID):

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>                                                                                                               
int main()   
{            
    pid_t pid = getpid();        //获取当前进程标识符
    pid_t ppid = getppid();      //获取当前进程的父进程的标识符
    printf("pid:%d ppid:%d\n", pid, ppid);
}   

通过系统调用创建进程--fork:

通过fork系统调用可以创建一个子进程,通过在Linux操作系统上使用man fork学习fork,我们可以总结出以下结论:

  • fork创建进程以原进程为模板,复制PCB的内容,拷贝代码和数据(共用一份代码,数据各自开辟空间,私有一份。采用写时拷贝)。


  • 调用一次fork有两个返回值,在父进程和子进程中分别返回;父进程中返回子进程的PID,子进程中返回0.

编译运行下面的代码,可以看到父进程的中的返回值恰好是子进程的PID:

int main()
{
    pid_t ret = fork();
    if(ret > 0)
    {
        printf("father:%d   ret:%d\n", getpid(), ret);//father
        sleep(1);
    }
    else if(ret == 0)
    {
        printf("child:%d   ret:%d\n", getpid(), ret);//child
    }
    else
    {                                                                                                                                
        perror("fork\n");
    }   
}

  • 父子进程的执行顺序不一定,取决于操作系统调度器;
  • 父子进程都从fork执行结束的位置开始执行;
  • fork失败的原因主要有:内存不足和创建的进程达到数目上限。

进程状态:

R(running):运行(就绪状态),不一定正在运行,也可能是在运行队列中;

S(sleeping):睡眠状态,意味着进程正在等待事件完成,在这个状态是可以打断的;


D(disk sleeping):磁盘休眠状态,也叫不可中断睡眠状态,该状态通常会等待IO的结束;(当密集的读写IO设备时会出现这个状态)

T(stopping):停止状态,可以通过SIGSTOP信号来停止进程,通过SIGCONT信号来让进程继续运行;

下面一段代码可以使进程一直处于运行状态,

#include <stdio.h>                                                                                                                   
int main()
{
    while(1)
    {   
        ;   
    }   
    return 0;
}

然后我们使用信号来使进程停止:


也可以使用信号来恢复:


t(tracing stop):跟踪状态;

X(dead):理论上存在;

Z(zombie):僵死状态。

僵尸进程:

    僵死状态是一个特殊的状态,当子进程退出而父进程未能读取子进程的返回值,就会产生僵死状态(进程)。这时候僵尸进程会一直等待父进程读取返回代码。

    所以,产生僵尸进程的条件是子进程退出,父进程还在运行同时未读取子进程的返回状态,子进程进入僵尸状态。

创建一个僵尸进程:

int main()
{      
    pid_t ret = fork();
    if(ret > 0)
    {
        while(1)
        {
            printf("father:%d   ret:%d\n", getpid(), ret);//father
            sleep(1);
        }
    }
    else if(ret == 0)
    {
        printf("child:%d   ret:%d\n", getpid(), ret);//child                                                                         
        sleep(1);
    }
    else
    {
        perror("fork\n");
    }
}           

僵尸进程的危害:

1 进程的退出状态必须被维持下去,因为他要告诉父进程,你交给我的任务完成的怎么样了。如果父进程一直不读取,子进程就会一直处于Z状态。

2 维护进程的退出状态要用数据维护,也是进程的基本信息,保存在(task_struct)PCB中;也就是说,如果Z状态一直不退出,PCB就要一直维护。

3  如果一个父进程建立了许多子进程而不进行回收,就会造成内存资源的浪费。因为保存进程信息需要结构体PCB,定义结构体需要在内存中开辟空间,又不进行回收,就会造成内存资源的浪费,造成内存泄漏

孤儿进程:

如果父进程提前退出,那么这时候子进程就会成为孤儿进程,孤儿进程会被1号进程领养。

下面来模拟实现一个孤儿进程:(3秒后父进程退出,子进程被1号进程回收)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
    pid_t ret = fork();                                                                                                              
    if(ret > 0)
    {   
        //father
        printf("father:pid %d  ppid:%d  ret:%d\n", getpid(), getppid(), ret);
        sleep(3);
    }   
    else if(ret == 0)                                                                                                                
    {
        //child
        while(1)
        {
            printf("child: pid %d  ppid:%d   ret:%d\n", getpid(), getppid(), ret);
            sleep(1);
        }
    }
    else
        perror("fork");
    return 0;
}

值得注意的是,孤儿进程不是状态,而僵尸进程是一个状态。

进程优先级:

基本概念:

  • CPU资源分配的先后顺序,就是指进程的优先权(priority)
  • 优先权高的进程有优先执行权利。配置进程优先级对任务环境的Linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样,把不重要的进程安排到某个CPU,可以大大改善系统性能。

查看优先级:

ps -l


ps -al

ps -elf

ps elf

PRI是进程的优先级,数值越小,优先级别越高。

NI是nice值,表示进程可被执行的优先级的修正数值。

PIR(new)=PIR(old)+nice值,当nice值为正时,优先值越大,优先级别越小;当nice值为负时,优先值越小,优先级别越大,越快被执行。

NI的取值范围是-20~19,共40个数据。

修改进程的优先级:

可以使用nice和renice命令修改进程优先级。

启动进程前调整:nice -n -5 ./hello

调整已经存在的进程:renice -5 -p 3498      //将PID为3498的进程的nice值改为-5

 用top查看进程优先级并修改进程优先级:

输入top回车->进入top后按“r”->输入进程PID->输入nice值


注:

  • 进程数目众多,而CPU只有少量甚至只有1个,所以为了高效完成任务,进程具有竞争性,它们要合理竞争相关资源,这样就有了优先级;
  • 多进程运行,需要独享各自的资源,做到进程运行期间互不干扰,进程具有独立性
  • 多个进程在不同的CPU下同时运行,叫做并行
  • 多个进程在一段时间内在同一CPU下用切换的方式共同推进,由于这个时间非常短,人一般察觉不到,就像进程是同时发生的一样,叫做并发
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程概念 的相关文章

  • 【VMware】虚拟机不能全屏的解决方法

    之前装了vmware workstation 8 最近装上新的ubuntu发现不能全屏 网上搜索后发现是因为没有安装vmware tools 现在就将本人安装vmware tools的过程介绍如下 1 加载vmwaretools 1 如下图
  • Kali Linux网络攻击

    文章目录 一 Kali Linux 使主机和虚拟机IP处于同一网段 1 关机 点击edit 虚拟机 2 网络连接 选择桥接bridge模式 3 现在开机 就和主机在同一网段下 可以fping g查找其它的IP地址了 二 查看局域网下所有ip
  • Linux操作系统之进程命令和库文件

    文章目录 一 有关进程命令 1 ps命令 显示当前终端信息 2 ps ef命令 查看当前终端进程的详细信息 二 前台程序和后台程序模式的切换 1 首先了解前台后台命令 2 前后台的切换 1 kill 命令 2 进程前后台切换 三 runle
  • 线程安全的单例模式:饿汉模式&懒汉模式

    目录 一 单例模式 二 饿汉模式 1 特点 2 实现关键 3 代码实现 三 懒汉模式 1 特点 2 实现关键 3 代码实现 一 单例模式 单例模式 一种典型的设计模式 应用场景 一个类只能实例化一个对象 向外提供统一访问接口的场景 作用 对
  • Base64系列第四篇 C/C++中使用Base64编码解码(从chromium库中抽取)

    本系列一共四篇 1 Base64系列第一篇 Base64介绍 2 Base64系列第二篇 python中使用Base64编码解码 3 Base64系列第三篇 C C 中使用Base64编码解码 使用boost库 4 Base64系列第四篇
  • 操作系统课程实践5_进程通信

    一 实验目的 1 初步了解Linux环境下进程创建和进程间通信的机制 2 掌握如何利用消息和共享内存进行通信的原理 3 利用POSIX API函数编写实例程序 4 实现父子进程间通过消息传递和共享内存方式进行通信 二 实验内容 编制两个程序
  • 守护进程的编程规则

    要理解守护进程的编程规则必须先搞明白进程组 会话 组长进程等关系 1 进程组 每个进程除了有一个进程ID之外 还属于一个进程组 进程组是一个或者多个进程的集合 每个进程组都有一个组长进程 组长进程的标识是 其进程ID和进程组ID相等 2 会
  • NFS高可用方案:NFS+keepalived+Sersync

    1 背景 因为某系统需要部署生产 但是云平台的nas存储资源不足需要重新采购 采购周期较长 需要有一个临时的解决方案 这样时候就需要采用nfs服务来提供网络存储服务了 在部署nfs服务的时候需要考虑生产环境需要有一定的高可用性 经过考虑之后
  • Linux操作系统之线程生产者消费者

    一 fork与互斥锁 Linux高性能服务器编程14 8 2 判断父子线程fork之后 是否使用的同一个锁 首先我们看一段代码 运行结果 根据上图我们发现 子进程变为阻塞状态 所以验证了进行fork之后 父子进程使用的不是同一个锁 如果使用
  • Linux操作系统之进程间通讯—共享内存与消息队列

    文章目录 一 共享内存 1 共享内存的原理 2 共享内存的实现 三 消息队列 1 消息队列原理 2 消息队列实现 一 共享内存 1 共享内存的原理 共享内存为多个进程之间共享和传递数据提供了一种有效的方式 共享内存是先在物理内存上申请一块空
  • 一个进程可以创建多少线程?

    理论上 一个进程可用虚拟空间是2G 默认情况下 线程的栈的大小是1MB 所以理论上一个进程可以创建2048个线程 当然更改编译器的设置可以创建多余2048个线程 因此 一个进程可以创建的线程数由可用虚拟空间和线程的栈的大小共同决定 只要虚拟
  • Linux操作系统之线程创建

    文章目录 一 了解线程 二 线程的创建 一 了解线程 什么是线程 线程是进程内部的一条执行路径或执行序列 二 线程的创建 pthread creat 创建线程 pthread exit 只退出当前线程 pthread join 等待线程结束
  • Linux的进程管理

    目录 1 概述 2 进程描述符 2 1 进程描述符的分配 2 2 进程描述符的存放 2 3 进程状态 2 4 进程上下文 2 5 进程家族树 3 进程的创建 4 进程的终结 5 线程的实现 1 概述 进程是执行期的代码 但是进程不止包括这样
  • Linux操作系统之mysql数据库简介

    文章目录 数据库的介绍 有关数据库的操作 有关数据表的操作 C语言访问mysql 事务 视图 索引 数据库的介绍 mysql数据库模型 关系型数据库与非关系型数据库 关系型数据库 指采用了关系模型来组织数据的数据库 关系模型就是指二维表格模
  • cgroup----devices子系统

    devices子系统 使用devices 子系统可以允许或者拒绝cgroup中的进程访问设备 devices子系统有三个控制文件 devices allow devices deny devices list devices allow用于
  • Linux mmap系统调用视角看缺页中断

    问题 1 mmap具体是怎么实现比read write少一次内存copy的 2 mmap共享映射和私有映射在内核实现的时候到底有什么区别 3 mmap的文件映射和匿名映射在内核实现的时候到底有什么区别 4 父子进程的COW具体怎么实现的 概
  • 什么是软连接,以及软连接在linux系统中的用法

    软连接是linux中一个常用命令 它的功能是为某一个文件在另外一个位置建立一个同步的链接 软连接类似与c语言中的指针 传递的是文件的地址 更形象一些 软连接类似于WINDOWS系统中的快捷方式 例如 在a文件夹下存在一个文件hello 如果
  • Linux项目实战C++轻量级Web服务器源码分析TinyWebServer

    目录 文章简介 一 先跑起来项目 二 再看项目结构 三 逐个击破 立下flag 文章简介 TinyWebServer是Linux下C 轻量级Web服务器 助力初学者快速实践网络编程 搭建属于自己的服务器 作为新手拿它练手入门再好不过的不二之
  • Centos 8.0中安装Redis服务器

    企业级开发中 经常需要把一些中间件安装在Linux服务上 主要考虑到linux服务器的性能吧 1 官网下载Linux版安装包 Redis 楼主使用的是 6 2 1 目前最新是6 2 6 差别不大 2 使用XShell 和Xftp连接Cent
  • Linux下软链接方法切换CUDA版本

    Linux下软链接方法切换CUDA版本 Linux下安装多版本的CUDA 直接切换版本 CUDA切换 sudo rm rf usr local cuda 删除之前的软链接 sudo ln s usr local cuda 10 0 usr

随机推荐

  • 基于javaweb的网上电商项目(前后端分离+java+vue+springboot+ssm+mysql+redis)

    基于javaweb的网上电商项目 前后端分离 java vue springboot ssm mysql redis 运行环境 Java 8 MySQL 5 7 Node js 10 开发工具 后端 eclipse idea myeclip
  • chrony服务部署,实现时间同步

    目录 chrony服务部署实验 实验一 第一台机器从阿里云同步时间 第二台机器从第一台机器同步时间 实验二 第一台服务器使用系统时间作为第二台服务器的时钟源 第一台服务器层级设置为6 问题排错 NTP 是网络时间协议 Network Tim
  • 记一次ubuntu16误删libc.so.6操作的恢复过程

    背景 操作系统 ubuntu16 glibc版本 2 23 修改原因 经过一系列报错和手工构建之后 vulkansdk成功安装 起码运行 vulkansdk成功 在进行 vulkaninfo进行验证时 报错 意思是当前glibc版本过低 需
  • 数字化转型面临的五大挑战

    如果将数字化转型分成五个阶段 全球大多数组织正处在第二和第三的僵局阶段 而处于第四和第五阶段的组织 全球不超过25 总体而言 未来数字化转型将面临五大挑战 一是陈旧的考核体系 数字企业需要新的度量标准来了解进度和引导投资 如果考核体系不变
  • 1_01李婉玲_函数_1019

    day04作业练习 作业01 小明和他家人在泰国旅游 到3个不同的饭店吃饭 账单 bill 分别是124元 48元和268元 为了给服务员小费 tip 小明创建了一个简单 的小费计算器函数 tipCalculator a 如果账单小于50元
  • spring jdbctemplate操作数据库

  • 【高数】Abel定理,幂级数的和收敛半径,不同幂级数收敛半径的比较,缺项幂级数的解法

    目录 一 收敛区间及收敛点 二 收敛半径的变化 三 借助正项级数敛散性求幂级数收敛区间 四 缺项幂级数的解法 五 小结 一 收敛区间及收敛点 现对该形式的幂级数进行如下讨论 1 幂级数的收敛区间 对称中心是x0 收敛半径是R 2 经有限次的
  • 最美丽的理论:爱因斯坦引力场方程的推导

    全文共2948字 预计学习时长9分钟 图源 superprof 伟大的前苏联物理学家列夫 朗道和叶夫根尼 利夫希茨在他们的著作 经典场论 中写道 建立在相对论基础上的引力场理论被称为广义相对论 它是由爱因斯坦建立的 并且可能是现存的物理理论
  • 局域网速度测试,三款软件轻松搞定(转)

    局域网络可谓随处可见 我们也十分关注其实际运行速度如何 比如两台计算机间的文件传输 访问对方计算机的快慢等 而决定局域网络速度的因素很多 又不可能通过简单的操作检测出速度的大小 同时也希望能有一些软件能帮助我们管理局域网 以方便故障的排查
  • LeetCode 1967. 作为子字符串出现在单词中的字符串数目(BM、KMP)

    给你一个字符串数组 patterns 和一个字符串 word 统计 patterns 中有多少个字符串是 word 的子字符串 返回字符串数目 子字符串 是字符串中的一个连续字符序列 示例 1 输入 patterns a abc bc d
  • 【GD32F303开发之开发工具的安装与配置】

    GD32F303开发系列文章目录 第一章 GD32微控制器开发工具的安装与配置 第二章 GD32基准工程实验 第三章 GD32串口通信实验 第四章 GD32EXMC与LCD显示实验 文章目录 GD32F303开发系列文章目录 前言 一 GD
  • 为了使用学校GPU集群而离线安装Python和pytorch

    参考 https blog csdn net zhangdongren article details 82685932 学校GPU集群为无网环境 所以要离线安装 1 下载python 源文件 2 解压到 下的某个目录 make编译源文件
  • 冒泡排序法

    冒泡排序 冒泡排序的排序过程 N个数最外层的for循环次数为 N 1 次 内层for循环为 N 1 i 次 每一轮凑从第1个数开始对比 每一次都是和它下一个元素对比 将最大值元素放到最后 其他元素向前移位 重复以上动作 知道N 1次循环全部
  • 钢琴音阶识别_基础知识:关于大小音阶的简单说明

    大小音阶 Scales 简单说明 音阶是音乐的构造块 building blocks 有上千种不同的音阶 有时称调式 每一种都有其特性与功能 peculiarities and functions 从我们称为 西方 音乐中 从欧洲国家起源的
  • Golang中常用的代码优化点

    写代码其实也有很多套路和经验 这篇介绍几个让golang代码更优雅的四个套路 大家好 我是轩脉刃 这篇想和大家聊一聊golang的常用代码写法 在golang中 如果大家不断在一线写代码 一定多多少少会有一些些代码的套路和经验 这些经验是代
  • Centos SSH免密登录

    1 防火墙操作相关 systemctl stop firewalld 永久关闭防火墙 systemctl disable firewalld 2 关闭Selinux 1 查看状态 getenforce 2 临时关闭 setenforce 0
  • java “Unsupported major.minor version 52.0错误“解决办法

    java Unsupported major minor version 52 0错误 解决办法 java Unsupported major minor version 52 0错误 解决办法 解决办法 java Unsupported
  • Landsat数据下载

    Landsat数据下载步骤 0 Landsat数据介绍 1 下载地址 2 下载步骤 2 1 检索数据 2 1 1 设置地点 有多种方法 2 1 2 选择时间范围 2 1 3 在Data Sets界面选择传感器 卫星或者传感器的名称 2 2
  • el-select可以输入选择项以及选择某一项后出现输入文本框

    效果 直接上代码做笔记 通过ref属性获取输入内容 在 blur中进行赋值 很好的实现了可选择 可输入
  • 进程概念

    基本概念 进程是程序的一个执行实例 从内核来看 进程是担当分配系统资源的实体 注 在Linux操作系统中 大多数指令都是创建了一个个的进程 操做系统如何管理内存 答 使用一个结构体 PCB 来描述进程 使用高效的数据结构来组织进程 描述进程