【Linux】进程学习(一):基本认识

目录

  • 1.基本概念
  • 2.初步理解
  • 3.描述进程-PCB
    • 3.1task_struct-PCB的一种
    • 3.2task_ struct内容分类
  • 4.组织进程
  • 5.查看进程
    • 5.1通过ps指令查看
    • 5.2通过系统目录查看
  • 6.通过系统调用获取进程的PID和PPID
  • 7.通过系统调用创建进程-fork初识

1.基本概念

  • 课本概念:程序的一个执行实例,正在执行的程序等
  • 内核观点:担当分配系统资源(CPU时间,内存)的实体。

2.初步理解

以前我们的任何启动并允许程序的行为,都是由操作系统帮助我们将程序转换成为进程,来完成特定的任务。(在Linux中,./运行一个程序。在windows中,鼠标双击运行一个程序。他们都将一个程序转换成了进程)

如图,我们将磁盘中的程序加载到了内存当中,形成了代码和数据。
在这里插入图片描述

但这并不算一个进程,操作系统为了管理这些加载到内存当中的代码和数据,需要先描述再组织,在内核当中为这些代码和数据创建一个个的数据结构对象。(操作系统书中叫PCB,Linux操作系统下是task_struct

在这里插入图片描述
例如:

  • 我们想要释放进程A,操作系统就在所有PCB中寻找关于进程A的,然后free释放掉对应的代码和数据以及PCB。
  • 我们想要运行进程中优先级最高的,操作系统就遍历所有的PCB找到对应的进程,将其加入CPU中运行。
  • 我们想要再运行一个程序,操作系统将磁盘中的程序加载到内存中转化为代码和数据。并且又为其创建一个PCB,将进程的属性加入PCB中,并链入原先的PCB链表当中。

因此:

  • 对进程的管理转化为对PCB链表进行增删查改。
  • 进程 = 加载到内存中的代码和数据 + 内核关于进程的相关数据结构

3.描述进程-PCB

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合
  • 课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct

3.1task_struct-PCB的一种

  • 在Linux中描述进程的结构体叫做task_struct。
  • task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

3.2task_ struct内容分类

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  • 其他信息

4.组织进程

可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct双链表的形式存在内核里。

5.查看进程

5.1通过ps指令查看

  • 单独使用ps命令,会显示所有进程信息。

ps -axj

在这里插入图片描述

通过对grep指令的搭配,可以查找想要查看的进程信息

ps -axj | head -1 && ps -axj |grep myprocess | grep -v grep

在这里插入图片描述

  • 因为grep也是进程,因此加入grep -v grep可以过滤掉grep进程信息。

5.2通过系统目录查看

进程的信息可以通过 /proc 系统文件夹查看

在这里插入图片描述

其中有很多文件夹都是以数字命名,这些数字其实就是对应进程的PID,对应文件夹当中记录着对应进程的各种信息。
在这里插入图片描述

当我们创建一个进程后,就会在/proc目录下创建对应的文件夹保存进程的信息。一旦我们关闭掉这个进程,/proc目录下相应的进程文件夹就会被删除。

6.通过系统调用获取进程的PID和PPID

通过使用系统调用函数getpid和getppid即可分别获取进程的PID和PPID。

在这里插入图片描述
使用下列代码测试。

在这里插入图片描述
运行结果,通过getpid获取的pid值与ps命令查询的值是相同的。
在这里插入图片描述
其次,通过不断启动终止进程,我们发现每次启动进程的pid都会改变,但是ppid并不会改变,这个ppid又是什么呢?

在这里插入图片描述
21615是我们的bash(命令行解释器)。
在这里插入图片描述
我们可以得到一些结论:

  • bash命令行解释器,本质上它也是一个进程!
  • 命令行解释器启动的所有程序,最终都会变成进程,而该进程对应的父进程都是bash

7.通过系统调用创建进程-fork初识

//创建子进程
//有两个返回值,创建成功给父进程返回子进程PID,给子进程返回0
//创建失败返回-1#include<unistd.h>int fork(void)

fork 函数能在当前进程下主动创建 子进程 ,用于代码程序中。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>int main()
{printf("AAAAAAAAAAAA\n");int ret = fork();printf("BBBBBBBBBBBB,PID: %d \n",getpid());sleep(1);return 0;
}

运行结果:

在这里插入图片描述
BBBBBBBB被打印了两次,可见fork系统调用之后程序就变成了两个执行流,即一个父进程一个子进程。

但通常我们可以根据fork的不同返回值,搭配if完成分流,使父子进程执行不同的代码。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
if(ret < 0)
{perror("fork");return 1;
}
else if(ret == 0)
{//childprintf("I am child : %d!, ret: %d\n", getpid(), ret);
}else
{//fatherprintf("I am father : %d!, ret: %d\n", getpid(), ret);
}sleep(1);return 0;
}

运行结果:
其中,fork之后的两个执行流,谁先执行由调度器决定

在这里插入图片描述

fork函数工作原理:

  • fork 创建子进程时,会新建一个属于子进程的PCB 然后把父进程 PCB 的大部分数据拷贝进子进程的PCB中,即子进程和父进程的PCB中的数据绝大部分是相同的。两个进程的PCB指向同一份代码和数据即两者共享一份代码和数据

我们知道进程是具有独立性的,父子进程同样具有独立性。

但父子进程两者共享同一份代码和数据,他们的独立性从何谈起?

  • 从代码层面:代码是只读的,父子进程只能读取代码,只不过可能读取的部分不同,相互不影响
  • 从数据层面:当其中一个执行流尝试修改数据时,OS 会给当前进程触发写时拷贝 机制

如何理解fork函数有两个返回值?

当return时,函数的主体功能已经完成,此时子进程已经被创建,所以两个进程都停留在fork函数中,等待返回。因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。

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

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

相关文章

计算机网络——05Internet结构和ISP

Internet结构和ISP 互连网络结构&#xff1a;网络的网络 端系统通过接入ISPs连接到互连网 住宅、公司和大学的ISPs 接入ISPs相应的必须是互联的 因此任何2个端系统可相互发送分组到对方 导致的“网络的网络”非常复杂 发展和演化是通过经济的和国家的政策来驱动的 问题&…

Elasticsearch:通过 ingest pipeline 对大型文档进行分块

在我之前的文章 “Elasticsearch&#xff1a;使用 LangChain 文档拆分器进行文档分块” 中&#xff0c;我详述了如何通过 LangChain 对大的文档进行分块。那个分块的动作是通过 LangChain 在 Python 中进行实现的。对于使用版权的开发者来说&#xff0c;我们实际上是可以通过 i…

在虚拟机上搭建CentOS环境并配置静态IP

在虚拟机上搭建CentOS环境并配置静态IP 在进行Linux系统的学习和实践时&#xff0c;搭建一个本地的CentOS环境是一个非常好的方式。本文将介绍如何使用虚拟机&#xff08;VM&#xff09;搭建CentOS环境&#xff0c;并配置静态IP&#xff0c;以便更好地进行网络管理和测试。 步…

结构体的大小以及内存对齐问题

结构体的大小怎么计算&#xff1f;什么是结构体的对齐&#xff1f; 首先想要直到结构体的大小需要先了解结构体的内存对齐。那么&#xff0c;什么是结构体的内存对齐&#xff1a; 什么是结构体内存对齐 结构体的对齐 就是 结构体类型数据在内存中按照一定的对齐规律储存。结…

jvm问题自查思路

本文聊一下最近处理了一些jvm的问题上&#xff0c;将这个排查和学习过程分享一下&#xff0c;看了很多资料&#xff0c;最终都会落地到几个工具的使用&#xff0c;本文主要是从文档学习、工具学习和第三方技术验证来打开认知和实践&#xff0c;希望有用。 一、文档 不仅知道了…

Vuex介绍和使用

1. 什么是Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库。它解决了在大型 Vue.js 应用程序中共享和管理状态的问题&#xff0c;使得状态管理变得更加简单、可预测和可维护。 在 Vue.js 应用中&#xff0c;组件之间的通信可以通过 props 和事件进行&#xff0c…

【代码】Processing笔触手写板笔刷代码合集

代码来源于openprocessing&#xff0c;考虑到国内不是很好访问&#xff0c;我把我找到的比较好的搬运过来&#xff01; 合集 参考&#xff1a;https://openprocessing.org/sketch/793375 https://github.com/SourceOf0-HTML/processing-p5.js/tree/master 这个可以体验6种笔触…

Idea里自定义封装数据警告解决 Spring Boot Configuration Annotation Processor not configured

我们自定对象封装指定数据&#xff0c;封装类上面一个红色警告&#xff0c;虽然不影响我们的执行&#xff0c;但是有强迫症看着不舒服&#xff0c; 去除方式&#xff1a; 在pom文件加上坐标刷新 <dependency><groupId>org.springframework.boot</groupId><…

编曲学习:旋律创作基础概念 和弦进行作曲 和弦外音使用 作曲技巧

旋律创作基础概念 和弦进行作曲 和弦外音使用 作曲技巧https://app8epdhy0u9502.pc.xiaoe-tech.com/live_pc/l_65be1ba7e4b064a83b92a3d7?course_id=course_2XLKtQnQx9GrQHac7OPmHD9tqbv文档https://app8epdhy0u9502.pc.xiaoe-tech.com/p/t_pc/course_pc_detail/camp_pro/cour…

图数据库 之 Neo4j - 环境搭建(2)

运行环境&#xff1a; centos7 Docker version 18.09.6 下载镜像 docker search neo4j docker pull neo4j 创建 neo4j 用户 # 创建 neo4j 用户 # -M 不创建用户的主目录 sudo useradd -M neo4j # usermod 用于修改用户属性命令 # -L 锁定用户&#xff0c;用户无法登录系统 user…

【QT+QGIS跨平台编译】之三十一:【FreeXL+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、FreeXL介绍二、文件下载三、文件分析四、pro文件五、编译实践一、FreeXL介绍 【FreeXL跨平台编译】:Windows环境下编译成果(支撑QGIS跨平台编译,以及二次研发) 【FreeXL跨平台编译】:Linux环境下编译成果(支撑QGIS跨平台编译,以及二次研发) 【FreeXL跨平台…

js手写Promise(上)

目录 构造函数resolve与reject状态改变状态改变后就无法再次改变 代码优化回调函数中抛出错误 thenonFulfilled和onRejected的调用时机异步then多个then 如果是不知道或者对Promise不熟悉的铁铁可以先看我这篇文章 Promise 构造函数 在最开始&#xff0c;我们先不去考虑Promi…