Linux--进程(1)

目录

前言

1.冯诺依曼体系结构

2. 操作系统(Operator System)--第一个被加载的软件

3.进程 

3.1基本概念 

 3.2Linux中的PCB

 3.3通过系统调用创建子进程-fork初识

fork:创建一个子进程

为什么要创建子进程?

fork的原理:

进一步了解fork的返回值

demo代码(一次创建多个子进程)


前言

在学习进程之前,我们要明白先了解两个东西:

                                1.体系结构----硬件上

                                2.操作系统----软件上


1.冯诺依曼体系结构

我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。

截至目前,我们所认识的计算机,都是有一个个的硬件组件组成

  • 输入单元:包括键盘, 鼠标,扫描仪, 写板等
  • 中央处理器(CPU):含有运算器和控制器等
  • 输出单元:显示器,打印机,磁盘,显卡,网卡,声卡等

关于冯诺依曼,必须强调几点:

  • 这里的存储器指的是内存(掉电易失)
  • 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)
  • 外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
  • 一句话,所有设备都只能直接和内存打交道。

再谈一个问题,为什么在体系结构中要有内存?

        冯诺依曼体系结构中要有内存,主要是因为内存可以适配CPU与外设之间速度不匹配的问题,从而提高整机效率。
        在冯诺依曼体系结构中,CPU的速度最快,而输入输出设备是最慢的。这会导致从输入设备传入数据到CPU处理,再从CPU传出已处理的数据到输出设备,这些过程之间的速度不匹配问题,降低了整机效率。为了解决这个问题,冯诺依曼体系引入了内存的概念。
        内存具有数据存储的能力,可以提前把数据准备好,CPU只需要从内存中拿数据进行处理。此外,根据局部性原理,当CPU需要获取某一行数据时,内存可以将该行数据之后的数据一同加载进来,而CPU处理数据和内存加载数据是可以同时进行的,这样下次CPU就可以直接从内存当中获取数据。
        因此,内存作为计算机数据的核心,可以大大提高数据处理的效率和速度。引入内存就把,效率问题,转化为了软件问题。

场景:

程序在运行的时候必须把程序先加载到内存中,为什么?

程序最终都是文件,文件都存储在硬盘上,硬盘属于外设;程序运行所产生的指令和数据,最终是要让cpu执行的;存储在硬盘中的程序(外设)最终会交给内存,是因为在数据层面,cpu只和内存交互,程序需要加载到内存中,再由内存交给cpu处理,这是冯诺依曼体系结构这么规定的。


对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上,请解释,从你登录上qq开始和某位朋友聊天开始,数据的流动过程。 从你打开窗口,开始给他发消息,到他的到消息之后的数据流动过程。如果是在qq上发送文件呢?
 聊天的时候,键盘输入的信息储存在内存中,并将其打包成特定的网络协议格式。CPU对这些数据进行处理,确保它们可以正确地通过网络发送。这些数据包通过网络发送到朋友的计算机上。朋友的计算机上的QQ程序处理这些接收到的消息,将其解包并显示在屏幕上。

如果是发送文件,这个文件首先被从硬盘读取到内存中。再以同样的方式发送到朋友那,朋友接收后,QQ程序处理这些数据包,去掉头信息,并将它们重新组装成原始的文件。这个文件随后被存储在朋友的计算机的硬盘上,朋友可以在其计算机上访问和查看这个文件。

这个过程内存也是起着核心作用。


2. 操作系统(Operator System)--第一个被加载的软件

 任何计算机系统都包含一个基本的程序集合,称为操作系统。笼统的理解操作系统包括:

  • 内核(进程管理,内存管理,文件管理,驱动管理)
  • 其他程序(例如函数库, shell程序等等)

设计OS的目的:

  • 与硬件交互,管理所有的软硬件资源
  • 为用户程序(应用程序)提供一个良好的执行环境

定位:在整个计算机软硬件架构中,操作系统的定位是: 一款纯正的“搞管理”的软件
在这里我们引入一张图:计算机的层状结构

在这里我们先谈硬件部分:

        首先,底层硬件是计算机系统的最底层部分,包括处理器、内存、硬盘、显卡等物理设备。这些硬件是计算机系统的基础,提供了运行程序和存储数据的能力。
        其次,驱动程序是介于底层硬件和操作系统之间的软件。由于不同的硬件厂商生产的硬件设备可能采用不同的技术和协议,因此操作系统无法直接识别和管理这些硬件。驱动程序的作用就是为操作系统提供与硬件设备进行通信和控制的能力。驱动程序包含有关硬件设备的信息,可以让操作系统识别和管理硬件,并与其进行交互。
        最后,操作系统是运行在计算机硬件之上的系统软件,它是计算机系统的核心。操作系统负责管理和控制计算机的硬件和软件资源,提供用户界面,支持多任务处理和文件系统等功能。操作系统通过与驱动程序进行交互,实现对底层硬件的管理和控制。

        底层硬件提供了计算机系统的物质基础,驱动程序为操作系统提供了与硬件进行交互和控制的能力,而操作系统则负责管理和控制整个计算机系统的资源和运行(先描述,在组织)。

为什么要有操作系统?
1. 管理硬件资源:操作系统负责管理计算机的各种硬件资源,如内存、处理器、硬盘、网络等,确保它们能够有效地被应用程序使用。
2. 提供用户接口:操作系统提供了用户与计算机之间的接口,使用户能够方便地与计算机进行交互,运行程序和管理文件。
3. 调度任务:操作系统负责对计算机上运行的各个任务进行调度和管理,确保它们能够按照一定的规则和优先级进行执行。
4. 提供安全性:操作系统通过访问控制和权限管理等机制来保护计算机系统的安全,防止未授权的访问和恶意软件的入侵。
总的来说,操作系统是计算机系统中不可或缺的部分,它为应用程序的运行和用户的操作提供了基础支持和保障,对下管理号软硬件系统(手段),对上提供一个良好的运行环境(目的)。

系统调用和库函数概念

  • 在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
  • 系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
     

3.进程 

承上启下

那在还没有学习进程之前,就问大家,操作系统是怎么管理进行进程管理的呢?很简单,先把进程描述起来,再把、进程组织起来!


3.1基本概念 

首先在操作系统中是不是只能运行一个程序呢?当然不是。

事实:

1.我们可以启动多个程序---我们一定要将多个.exe加载到内存

2.操作系统要不要管理多个加载到内存的程序呢?要的

3.操作系统如何管理加载到内存的程序 呢?先描述,再组织!

操作系统管理加载到内存的程序通常遵循以下步骤:

  • 加载程序:当用户启动一个程序时,操作系统首先会将程序的可执行文件从磁盘加载到内存中。这个过程涉及将程序的代码段、数据段和堆栈段等部分加载到内存的不同区域。
  • 设置程序的执行环境:操作系统会为每个加载到内存的程序设置一个独立的执行环境,包括分配内存空间、建立程序的数据结构、初始化寄存器等。
  •  创建进程控制块(PCB):操作系统会为每个加载到内存的程序创建一个进程控制块(PCB)是操作系统中用于管理进程的数据结构,它包含了进程的各种信息和状态,PCB对象会根据自己所包含的信息在内存中找到自己对应的程序记录和管理程序的运行状态、资源占用情况、优先级等信息,在内存中的PCB对象会形成数据结构方便操作系统的管理(增删查改)
  • 分配资源:操作系统会根据程序的需求分配各种资源,如内存空间、CPU时间片、文件句柄等,以确保程序能够正常运行。
  • 运行程序:一旦程序被加载到内存并设置好执行环境,操作系统会按照调度算法将程序放入就绪队列,等待CPU执行。当程序获得CPU时间片时,操作系统会将控制权交给程序,程序开始执行。

为什么加载到内存加载到内存,变成进程之后,我们要给每一个进行形成一个PCB对象呢?因为操作系统要进行管理

通以上的操作其实就将对进程的管理,转化成为了对PCB对象的管理,变成了操作系统对PCB对象所形成的数据结构的增删查改。

在这里我们就可以对进程下定义了:

进程= 内核PCB对象(内核数据结构)+可执行程序


 3.2Linux中的PCB

PCB:是操作系统学科的叫法。在Linux中,PCB就是task struct。

我们来见一见Linux中的task struct。这是Linux内核的源代码,里面确实存在这个结构体

task struct中有哪些属性?

命令ps axj可以查看当前的进程

我们生成了一个mytest的可执行程序,并运行它,这时候就变成了进程,程序运行结束进程也就结束了(进程是有“生命”的)。

下面是它所对应的进程,我们发现在mytest进程下面还有一个grep的进程,这是为什么?

这是因为几乎所有的指令,都是程序,运行起来也要变成进程,grep当然也不例外。


  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。

在上图中,PID一栏就是标识符,下面在程序中可以通过getpid函数查看PID

除了PID外还有PPID(父进程),在Linux中每个人进程都有一个父进程,而父进程可能有多个子进程。每一次启动进程PID几乎都会变化,因为我的进程是一个新的进程!而父进程不会变,子进程有父进程创建

我们可以查询16986这个进程,发现它就是bash(命令行解释器)。

除了ps ajx查看进程的方式,我们还可以通过proc文件去查看正在运行的程序的信息

cwd表示当前的进程的工作目录:我们在学习C语言的时候,会学习创建文件,如果你没有指定完整的路径,那么这些操作就会在这个工作目录下进行。

exe记录的是进程可执行文件的位置

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

 3.3通过系统调用创建子进程-fork初识

fork:创建一个子进程

我们先来看一段代码:

我们发现after打印了两次,一旦fork后会创建子进程,这时就会有两个执行分支了,两分支都要执行printf。我们还发现最后一个after,他的父进程就是上一个after,而上面两个的父进程是24662(bash)fork之后,后续的代码父和子都会执行

再看一段代码:

我们发现,fork是有返回值的;在父进程中fork会返回子进程的ID,因为父进程需要记住创建的子进程。在子进程中,会返回0/-1,返回0就代表fork函数执行成功,返回0来标识子进程,返回-1就代表fork函数出错了


为什么要创建子进程?

当然是要子进程帮父进程去办事,让父子做不同的事情。

看下面的代码:使用if语句进行分流,让父子做不同的事情。

通过返回值的不同来区分父子进程,进而让父子进程去做不同的事情。


fork的原理:

1.每一个进程=内核数据结构+可执行代码和数据

2.创建一个进程的时候,系统中会多一个进程;因此会给子进程创建一个task_struct,但是子进程没有代码和数据进行执行,这时子进程会默认指向父进程的代码和数据。

3.但这样是不行的,这时我们虽然是共享了代码,但要使得这个操作有意义,我们得执行不同的操作,因此fork函数就通过返回值的不同,让父与子去执行代码块不同的部分。当然这代码依旧是来自父亲,fork之后,儿子就帮父亲分担了一部分工作。

4.子进程为什么能去调度代码,是因为子进程会继承父进程中task_struct的大多数属性,以父进程为模板创建子进程。


进一步了解fork的返回值

1.给父进程返回父进程的pid,给子进程返回0,为什么?

父:子 = 1:n,父亲可以有很多儿子,而儿子只有一个父亲,因此子进程需要返回自己的ID给父亲,方便父亲唯一性的确认和控制这个子进程,而父亲是唯一的,不需要进行标识。

2.fork 函数为什么会返回两次?

调用fork只能是父进程去调用fork。如果一个函数,已经运行到了最后开始执行return的时候,这个函数的核心逻辑做完了吗?当然做完了。fork是函数,fork执行完了也需要return。而fork也是有自己的执行代码的,在return之前子进程就已经被创建了,创建好了之后,父子进程代码共享,return也是代码,那么子进程当然也可以执行return,因此fork会返回两次,一次是父进程返回的,另一次当然是子进程返回的。

3.这里还有一个最让人不能理解的地方,同一个变量id,怎么可能既等于0,又大于0 呢?

一个进程崩溃了,会不会影响其它进程?当然是不会的。

进程之间是具有独立性的,互不影响。

这个返回值也被存储在一个名为id的变量中,但这个变量是子进程的局部变量,与父进程中的id变量是完全独立的。
这两个返回值是通过操作系统内核的调度机制实现的,它确保了父进程和子进程在逻辑上是并发的,但实际上它们在物理上可能是交替执行的。由于这两个进程有独立的地址空间,因此它们各自的局部变量(即使变量名相同)也是相互独立的。
这就是为什么你会看到id变量似乎“同时”存入了两个值,但实际上这两个值分别属于两个不同的进程上下文。每个进程都有自己的变量副本,这些变量在进程内部是唯一的,并且互不干扰。


demo代码(一次创建多个子进程)

代码:

#include <stdlib.h>

const int num = 10;
void worker()
{
	int cnt = 12;
     while (cnt)
	 {
		printf("child %d is running,cnt:%d\n", getpid(), cnt);
		cnt--;
		sleep(1);
	 }
}
int main()
{
	for (int i = 0; i < num; i++)
	{
		pid_t id = fork();
		if (id < 0) break;
		if (id == 0)
		{
			//子进程
			worker();
			exit(0);//让子进程退出                           
		}
		printf("father create child process success,child pid:%d\n", id);
	}
	//只有父亲进程会执行到这里
	sleep(15);
	return 0;
}

在主函数 main 中,通过循环创建了10个子进程,每个子进程通过调用 worker 函数来输出信息,然后退出。父进程在创建子进程后会打印子进程的PID,并在所有子进程创建完成后通过 sleep(15) 来延迟一段时间。需要注意的是,父进程在创建子进程时应该检查 fork() 的返回值以处理可能的错误情况。

我们发现最后子进程都退出了,有<defunct>的标识,留下来的只有父进程

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】调试器-gdb的使用说明(调试器的配置,指令说明,调试过程说明)

目录 00.背景 01.安装 02.生成调试信息 03.调试过程 00.背景 在软件开发中&#xff0c;通常会为程序构建两种不同的版本&#xff1a;Debug模式和Release模式。它们之间的区别主要在于优化级别、调试信息、错误检查等方面&#xff1a; 1.Debug 模式&#xff1a; 优化级别低…

灵境矩阵平台x百度---智能体(一)

什么是数据插件 大模型插件:大语言模型插件是随着大语言模型发展而诞生的全新插件。大语言模型插件的核心是Web API独立于大语言模型&#xff0c;插件开发过程不受大语言模型的约束&#xff0c;同时没有开发语言的限制&#xff0c;更加通用&#xff0c;只要WebAPI遵循RESTfuI相…

如何在 Odoo 17 的 齿轮菜单⚙️ 中添加新菜单

在 Odoo 中&#xff0c;齿轮菜单是一个重要组件&#xff0c;允许用户访问与系统内不同模型和功能相关的各种配置选项和设置。它通常由位于用户界面左上角的齿轮或齿轮图标表示。下图显示了 "sale.order "模型的齿轮菜单。 默认情况下&#xff0c;我们在 CogMenu 中提…

js 实现动画的两种方案对比:setTimeout vs RAF (requestAnimationFrame)

setTimeout 需手动控制频率&#xff0c;页面隐藏后仍会执行动画&#xff0c;更加耗费性能。 requestAnimationFrame 简称 RAF , 会在浏览器中每次刷新屏幕时调用一个函数&#xff0c;用于创建平滑的动画&#xff0c;因为它会自动适应屏幕的刷新率&#xff0c;无需手动控制频率。…

实战whisper语音识别第一天,部署服务器,可远程访问,实时语音转文字(全部代码和详细部署步骤)

Whisper是OpenAI于2022年发布的一个开源深度学习模型&#xff0c;专门用于语音识别任务。它能够将音频转换成文字&#xff0c;支持多种语言的识别&#xff0c;包括但不限于英语、中文、西班牙语等。Whisper模型的特点是它在多种不同的音频条件下&#xff08;如不同的背景噪声水…

今天聊聊新零售

一、什么是新零售&#xff1f; 2016年&#xff0c;在杭州举行的“云栖大会”上&#xff0c;马云发表了讲话&#xff0c;首次提出了“新零售”这一概念。 1.1 新零售概念 新零售&#xff0c;英文是New Retailing&#xff0c;新零售是对人货场的重构。人是消费者、销售人员、…

C++的vector类(一):vector类的常见操作

目录 前言 Vector类 遍历与初始化vector ​vector的扩容机制 vector的对象操作 find与insert 对象数组 前言 string类中还有一些内容需要注意&#xff1a; STL 的string类怎么啦&#xff1f; C面试中string类的一种正确写法 C STL string的Copy-On-Write技术 C的st…

网络编程 - 套接字

1、预备知识 1.1、理解源IP地址和目的IP地址 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址&#xff1b; 思考: 我们光有IP地址就可以完成通信了嘛? 想象一下发qq消息的例子, 有了IP地址能够把消息发送到对方的机器上, 但是还需要有一个其他的标识来区分…

kafka面试篇

消息队列的作用&#xff1a;异步、削峰填谷、解耦 高可用&#xff0c;几乎所有相关的开源软件都支持&#xff0c;满足大多数的应用场景&#xff0c;尤其是大数据和流计算领域&#xff0c; kafka高效&#xff0c;可伸缩&#xff0c;消息持久化。支持分区、副本和容错。 对批处理…

使用ansible剧本进行lvm分盘

使用 Ansible 剧本&#xff08;Playbook&#xff09;进行 LVM 分区管理是一种自动化的方式&#xff0c;可以帮助管理员在多台主机上批量管理逻辑卷。 部署环境 3台主机&#xff0c;添加硬盘 ansible-galaxy collection install community.general 联网执行&#xff0c;下…

蓝桥杯算法心得——游戏(优先队列)

大家好&#xff0c;我是晴天学长&#xff0c;优先队列的题&#xff0c;式子化简非常重要&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1) .游戏 2) .算法思路 附近最小 1.接收数据 2.找出最小的&#…

docker 配置国内阿里镜像源

在/etc/docker/目录下新建daemon.json文件 在文件中写入 {"registry-mirrors": ["https://jmphwhtw.mirror.aliyuncs.com"] } 以管理员身份运行命令 systemctl daemon-reload systemctl restart docker

羊大师羊奶靠谱么?消费口碑深度讲解

羊大师羊奶靠谱么&#xff1f;消费口碑深度讲解 羊大师羊奶&#xff0c;作为羊奶市场的一颗璀璨明星&#xff0c;其靠谱性一直备受广大消费者的关注。那么&#xff0c;羊大师羊奶究竟靠不靠谱呢&#xff1f;这需要我们从品牌实力与消费口碑两个方面进行深度解析。 从品牌实力来…

小米相册提取表格选项消失解决方法

小米相册这次的提取表格选项消失 故障原因&#xff1a; 因为部分用户将小爱视觉&#xff08;原名扫一扫&#xff09;这个应用给卸载了导致 解决方法 应用商店下载 小爱视觉 安装后授权即可使用 注意&#xff1a;系统最好为最新的 Xiaomi HyperOS系统

PFXA401SF Millmate控制器400设计用于提供大量功能 Brown Boveri BBC

PFXA401 Millmate控制器400设计用于提供大量功能&#xff0c;同时具有高度的用户友好性。 控制单元涵盖了所有边缘传感器的安装可能性。这意味着用户只需按照逐步说明设置控制单元&#xff0c;并计算正确的料带边缘和中心位置及宽度。 计算相对于轧机的真实带材位置和宽度 过滤…

RabbitMQ在Java中使用 SpringBoot 从基础到高级

充分利用每一个监听者 需要充分利用每一个消费者&#xff0c;需要在配置文件中加上prefetch配置并设置为1 rabbitmq:listener:simple:prefetch: 1 # 每次只能获取一条消息&#xff0c;处理完成才能获取下一个消息创建交换机和队列 创建队列 "fanout.queue1"&…

云农场种植、领养、收获,认养模式新浪潮

​ 小编介绍&#xff1a;10年专注商业模式设计及软件开发&#xff0c;擅长企业生态商业模式&#xff0c;商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地&#xff1b;扶持10余个电商平台做到营收过千万&#xff0c;数百个平台达到百万会员&#xff0c;欢迎咨询。 在…

服务器中了mallox勒索病毒还能恢复数据吗?

什么是mallox勒索病毒&#xff1f; mallox是一种最近多发的勒索病毒类型&#xff0c;它主要针对企业的Web应用和数据库服务器进行攻击。mallox后缀的勒索病毒会加密用户的重要文件数据并以此为要挟索要赎金。该类病毒会绕过企业的防火墙和各种防护软件&#xff0c;对目标设备进…

Python 将HTML转为PDF、图片、XML、XPS格式

网页内容是信息传播的主要形式之一。在Web开发中&#xff0c;有时候我们需要将HTML文件以不同的格式保存或分享&#xff0c;比如PDF、图片&#xff08;如PNG或JPEG&#xff09;、XML或XPS等。这些格式各有优势&#xff0c;适合不同的用途。在这篇文章中&#xff0c;我们将介绍如…

GPU 使用率监测及可视化

1. 使用 nvidia-smi可视化 直接在终端输入nvidia-smi动态查看GPU的使用情况watch -n 0.5 nvidia-smi其中0.5表示每隔0.5秒更新一次,时间可以调整 2. 使用nvitop可视化 2.1 nvitop的使用 (1) 安装 pip install nvitop(2) 查看GPU使用率 nvitop