Linux 操作系统 进程(1)
什么是进程
想要了解什么是进程,或者说,为什么会有进程这个概念,我们就需要去了解现代计算机的设计框架(冯·诺依曼体系):
计算机从设计之初就以执行程序为核心任务,也就是运算器从内存中读取,也只从内存中读取,输入设备也只能输入到内存中。在早期计算机系统中,计算机一次只能运行一个程序,所有资源都被这个程序独占。随着需求的增加,计算机需要能够同时运行多个任务,比如一个任务处理文件读写,另一个任务计算数据。这时,系统需要一种机制来管理多个程序的执行,确保它们能够公平、有效地利用计算机的资源,这就是进程概念产生的原因。
进程的定义
进程是操作系统中执行程序的一个实例,它包含了程序运行所需的所有信息和资源。简单来说,进程就是操作系统为运行中的程序提供的一个执行环境,包括程序代码、数据、打开的文件、内存空间和处理器时间等。一个程序在操作系统中可能运行多个实例,每个实例就是一个独立的进程。
每个进程通常包含以下几个部分:
- 可执行程序代码:程序的二进制指令。
- 进程的内存空间:包括堆、栈、数据段等。
- 进程状态信息:CPU寄存器、程序计数器等,记录当前进程执行的具体状态。
- 调度信息:操作系统需要的信息,用来决定何时执行该进程。
这些也就是计算机或者说是操作系统用来描述每一个需要执行的程序的方法,在linux里,描述程序的结构体叫做 task_struct 也叫做PCB (Process Control Block,进程控制块)PCB是一个概念,task_struct则是在linux里PCB的具体表现。
struct task_struct {volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */struct thread_info *thread_info;atomic_t usage;unsigned long flags; /* per process flags, defined below */unsigned long ptrace;int lock_depth; /* Lock depth */int prio, static_prio;struct list_head run_list;prio_array_t *array;
}
这是在 linux-2.6.11.1 截取的task_struct 片段,通过这个片段,我们可以看到操作系统用来描述进程信息的部分属性。
state
表示进程的当前状态(可运行、不可运行等)。usage
是引用计数,记录进程被使用的次数。prio
和static_prio
是进程的优先级,用于调度。run_list
用于将进程挂入运行队列,array
管理进程的优先级队列。
struct list_head {struct list_head *next, *prev;
};
而这里链接进程进入运行队列的结构就是这个结构体,
通过上篇博客(不同结构体之间的链接-CSDN博客)的字节运算从而获得每一个结构体的成员。
为什么需要进程?
引入进程的核心原因在于多任务处理和资源管理。现代计算机需要同时运行多个任务,而进程是管理这些任务的一种机制。进程可以:
- 隔离任务:每个进程运行在自己的内存空间中,避免相互影响。这种隔离性提高了系统的安全性和稳定性。
- 资源管理:操作系统通过进程来分配 CPU、内存和I/O设备等资源,确保每个进程都能公平地使用系统资源。
- 并发执行:通过多任务调度,操作系统可以在一个 CPU 上快速切换进程,使得多个进程看似同时执行,提升系统的利用效率。
进程的出现,使得操作系统能够高效管理多个任务,并为每个任务提供独立、受保护的执行环境。
查看进程
在window操作系统中,由于图形化的原因,我们可以通过任务管理器更加方便直接的看到当前计算机正在运行的进程,同时我们还可以看到他的基本信息,那么在Linux系统中,我们该如何查看进程呢 ?
我们可以直接在 /proc/ 文件夹里查看进程
这些蓝色的数字就是进程的PID (唯一标识符) ,如果我们想要查进程信息,同样可以进入文件夹内查看
大多数进程信息同样可以使用top和ps这些用户级工具来获取
我们可以写一个一直循环的进程用来使用ps查询
#include <stdio.h>
#include <unistd.h>int main()
{while (1){sleep(5); // 暂停 5 秒printf("mypid: %d\n"); }return 0;
}
为什么有两个呢,因为作为查询任务的 grep 也是一个进程 ,同样,我们也可以使用系统接口,在程序内获取进程PID 和父进程的PID (PPID)
每一次我们执行程序,进程PID都是改变的
top命令大多数情况下都是用在进程优先级上,我们在优先级那里在回顾top的使用
创建进程
在系统给出的系统调用接口中,也有创建子进程的相关函数,那就是 fork() 。
fork()
函数是 Unix 和 Linux 系统中用于创建新进程的系统调用。它是进程控制的一部分,用于实现多任务处理。fork()
在调用时会创建一个新的进程,这个新进程是调用进程的一个副本,称为子进程
- 创建新进程:
fork()
会复制调用进程的所有属性,创建一个新的进程。 - 返回值:
- 在父进程中,
fork()
返回新创建的子进程的 PID。 - 在子进程中,
fork()
返回0
。 - 如果
fork()
失败,它会返回-1
,并设置errno
以指示错误原因。
- 在父进程中,
我们通常使用 if 来分流父进程与子进程
#include<stdio.h>
#include<unistd.h> int main()
{ pid_t id = fork(); if(id==0) //子进程 { int i = 5; while(i--) { printf("我是子进程 pid : %d, ppid : %d\n",getpid(),getppid()); sleep(1); } } else if(id>0) { int i=7; while(i--) { printf("我是父进程 pid: %d,ppid: %d\n",getpid(),getpid()); sleep(1); } } else { perror("进程创建失败\n"); } return 0;
}
fork()函数
上述代码,我们可以看出来,我们创建了一个子进程,但是,在以往我们学习C语言的经验里,一个程序里,一个值怎么进入两个完全不同的if判断呢,那我们最直观的想法就是,父进程跟子进程使用的数据并不是用一个甚至并没有在一起。
在fork()官访问当中,我们可以看到
内存空间的独立性
-
进程复制:
- 当调用
fork()
时,操作系统会创建一个新的进程(子进程),这个子进程是父进程的一个副本。在内存中,这意味着子进程会有一份与父进程相同的内存内容,包括代码、数据、堆栈等。
- 当调用
-
独立的内存空间:
- 虽然父进程和子进程在
fork()
时内存内容是相同的,但它们的内存空间是独立的。每个进程在其自己的地址空间中操作,因此一个进程的内存更改不会直接影响到另一个进程的内存。
- 虽然父进程和子进程在
-
写时复制(Copy-on-Write):
- 在现代操作系统中,
fork()
采用了一种优化机制叫做写时复制(Copy-on-Write)。最初,父进程和子进程共享相同的物理内存页,只有当其中一个进程试图修改这些内存页时,操作系统才会复制这些页,确保每个进程拥有自己的副本。这种机制减少了fork()
操作的开销。
- 在现代操作系统中,
子进程与父进程的分流
当我们了解 fork()函数后,了解了fork()函数之后的代码是子进程与父进程共有的,当子进程要修改某一个变量的值时,系统才会给子进程拷贝一份这个值,并开辟空间给其进行修改,那我们是不是可以通过取地址 id 的地址来获得子进程存放数据的地址呢?
#include<stdio.h>
#include<unistd.h> int main()
{ pid_t id = fork(); if(id==0) //子进程 { printf("%p\n",&id); } else if(id>0) { printf("%p\n",&id); } else { perror("进程创建失败\n"); } return 0;
}
我们惊奇的发现,两个id的地址竟然是一样的,那我们之前的拷贝的id在哪里,同一个地址给出的id值竟然会不一样 ! 其实这是操作系统包含内存的设计,如果让我们的程序简简单单就可以访问到物理地址,那么操作系统很容易就崩溃了。对与每一个进程,或者说是每一个程序,操作系统都平等分配一个虚拟地址空间,通过这个虚拟地址空间跟页表映射到真实的物理地址,那么也就是说,这两个id不同的是物理地址。
当fork函数返回时,对id进行了写时拷贝,子程序的页表重新映射到操作系统存放的新id的物理地址(简图)
当子进程被创建时,PCB等内容被填充,父子进程指向相同的代码,同时,父子进程都有了属于自己的task_struct,可以被操作系统调度并执行了,同时由于,直接拷贝导致消耗过大,也就有了,修改数据时分配空间同时让子进程的页表指向该空间从而获得不同的数据。页表的设计,将虚拟地址跟物理地址连接到一起并且让内存单独维护内存,进程单独维护进程,保护数据的同时,解耦两部分。
ps: Linux 源码下载 Index of /pub/linux/kernel/
相关文章:

Linux 操作系统 进程(1)
什么是进程 想要了解什么是进程,或者说,为什么会有进程这个概念,我们就需要去了解现代计算机的设计框架(冯诺依曼体系): 计算机从设计之初就以执行程序为核心任务,也就是运算器从内存中读取,也只从内存中…...

clickhouse-v24.1-离线部署
部署版本 数据库版本:24.1.1.2048 jdk版本:jdk8 4个文件(三个ck的包): OpenJDK8U-jdk_x64_linux_hotspot_8u382b05.tar clickhouse-client-24.1.1.2048.x86_64.rpm clickhouse-common-static-24.1.1.2048.x86_64.…...

安卓13删除app 链接库警告弹窗Detected problems with app native
总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码修改彩蛋1.前言 有些客户的APP,打开首次会弹窗提示窗口, Detected problems with app native libraries (please consult log for detail):,需要删除这个窗口,避免挡住用户APP。而且这个提示有些app是以t…...

第四次北漂----挣个独立游戏的素材钱
第四次北漂,在智联招聘上,有个小公司主动和我联系。面试了下,决定入职了,osg/osgearth的。月薪两万一。 大跌眼镜的是,我入职后,第一天的工作内容就是接手他的工作,三天后他就离职了。 我之所以…...

漫谈设计模式 [12]:模板方法模式
引导性开场 菜鸟:老大,我最近在做一个项目,遇到了点麻烦。我们有很多相似的操作流程,但每个流程的细节又有些不同。我写了很多重复的代码,感觉很乱。你有啥好办法吗? 老鸟:嗯,听起…...

CSS学习10[重点]--浮动、浮动的效果以及内幕特性
CSS布局——浮动 前言一、普通流二、浮动三、什么是浮动?四、浮动的内幕特性总结 前言 CSS盒子布具的三种机制:普通流(标准流)、定位、浮动。 一、普通流 普通流:网页内元素自上而下,从左到右排序。 二、浮动 浮动…...

matlab基本语法
基本语法 变量命名规则 区分大小写长度不超过63位字母开头,可以有字母、下划线和数字组成,但不能使用标点应该简洁明了 命令行窗口 >>>clc 清楚命令窗口 >>> claer all 清理工作区内容 注释 %% 注释符 数据类型 1.数字 11 2…...

【Leetcode152】乘积最大子数组(动态规划)
文章目录 一、题目二、思路三、代码 一、题目 二、思路 (0)读懂题意:题目的“连续”是指位置的连续,而不是说数字的连续,这是个大坑。 (1)确定状态:定义两个状态来记录当前子数组的…...

STM32(十二):DMA直接存储器存取
DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源。(运行内存SRAM、程序存储器Flash、寄存器) 12个独立可配置的通道&…...

关于我2020年7月至今(2024.9)的“炒股”经历和感受
声明:我远不是一个成熟的投资者(这个名词太大了,我那三瓜两枣似乎完全配不上投资者这三个字,或者“小小散”更加贴切)。本文不构成任何入(股)市的引导或者买卖股票的建议。 “炒股”这个词,相信绝大多数人看来都-是一个贬义词&…...

【Tools】Prompt Engineering简介
摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样 🎵 方芳《摇太阳》 大模型中的Prompt Engineering是指为了提高大模型在特定任…...

多路转接之select(fd_set介绍,参数详细介绍),实现非阻塞式网络通信
目录 多路转接之select 引入 介绍 fd_set 函数原型 nfds readfds / writefds / exceptfds readfds 总结 fd_set操作接口 timeout timevalue 结构体 传入值 返回值 代码 注意点 -- 调用函数 select的参数填充 获取新连接 注意点 -- 通信时的调用函数 添…...

乐鑫安全制造全流程
主要参考资料: 【乐鑫全球开发者大会】DevCon24 #10 |乐鑫安全制造全流程 乐鑫官方文档Flash加密: https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/security/flash-encryption.html 【ESP32S3】使用 Flash 下载工具完成 Flash 加密功能…...

〖open-mmlab: MMDetection〗解析文件:configs/_base_/schedules
详细解析三个训练调度文件:schedule_1x.py、schedule_2x.py、schedule_20e.py 在深度学习模型训练过程中,训练调度(Training Schedule)是至关重要的,它决定了模型训练过程中学习率(Learning Rate, LR&…...

Android之Handler是如何保证延迟发送的
目录 核心组件延迟发送消息的工作原理具体步骤1. 创建 Handler:2.发送延迟消息3.消息入队列4.消息出队和处理: 关键点总结 在 Android 中,Handler 是用于在不同线程之间传递和处理消息的工具。它可以用于定时任务、延迟执行任务等。Handler 如何保证延迟发送消息的核…...

定位信标、基站、标签,定位信标是什么
定位信标、基站、标签,定位信标是什么 今天给各位分享定位信标、基站、标签的知识,其中也会对定位信标是什么进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧! 怎样做人员定位啊? 〖…...

2024国赛数学建模B题完整分析参考论文38页(含模型和可运行代码)
2024 高教社杯全国大学生数学建模完整分析参考论文 B 题 生产过程中的决策问题 目录 摘要 一、问题重述 二、问题分析 三、 模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1样例代码(仅供参考) 4.…...

Hive是什么?
Apache Hive 是一个基于 Hadoop 的数据仓库工具,用于在 Hadoop 分布式文件系统(HDFS)上管理和查询大规模结构化数据集。Hive 提供了一个类似 SQL 的查询语言,称为 HiveQL,通过这种语言可以在 HDFS 上执行 MapReduce 作…...

计算机网络:http协议
计算机网络:http协议 一、本文内容与前置知识点1. 本文内容2. 前置知识点 二、HTTP协议工作简介1. 特点2. 传输时间分析3. http报文结构 三、HTTP版本迭代1. HTTP1.0和HTTP1.1主要区别2. HTTP1.1和HTTP2主要区别3. HTTPS与HTTP的主要区别 四、参考文献 一、本文内容…...

【stata】自写命令分享dynamic_est,一键生成dynamic effect
1. 命令简介 dynamic_est 是一个用于可视化动态效应(dynamic effect)的工具。它特别适用于事件研究(event study)或双重差分(Difference-in-Differences, DID)分析。通过一句命令即可展示动态效应…...

文心一言 VS 讯飞星火 VS chatgpt (342)-- 算法导论23.2 1题
一、对于同一个输入图,Kruskal算法返回的最小生成树可以不同。这种不同来源于对边进行排序时,对权重相同的边进行的不同处理。证明:对于图G的每棵最小生成树T,都存在一种办法来对G的边进行排序,使得Kruskal算法所返回的…...

部署若依Spring boot项目
nohup和& nohup命令解释 nohup命令:nohup 是 no hang up 的缩写,就是不挂断的意思,但没有后台运行,终端不能标准输入。 nohup :不挂断的运行,注意并没有后台运行的功能,就是指,用nohup运行命令可以使命令永久的执行下去,和用户终端没有关系,注意了nohup没有后台…...

oc打包:权限弹窗无法正常弹出
在遇到编写了权限无法弹出弹窗时,需要查看是不是调用时机不对,这里直接教万能改法。 将权限获取方法编写在applicationDidBecomeActive 进入前台的生命周期接口中,如下: if (@available(iOS 14, *)) {NSLog<...

深入理解RxJava:响应式编程的现代方式
在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJ…...

Maven 依赖漏洞扫描检查插件 dependency-check-maven 的使用
前言 在现代软件开发中,开源库的使用愈加普遍,然而这些开源库中的漏洞往往会成为潜在的安全风险。如何及时的发现依赖的第三方库是否存在漏洞,就变成很重要了。 本文向大家推荐一款可以进行依赖包漏洞检查的 maven 插件 dependency-check-m…...

2. 下载rknn-toolkit2项目
官网链接: https://github.com/airockchip/rknn-toolkit2 安装好git:[[1. Git的安装]] 下载项目: git clone https://github.com/airockchip/rknn-toolkit2.git或者直接去github下载压缩文件,解压即可。...

xhr、ajax、axois、fetch的区别
一、XMLHttpRequest (XHR)、AJAX、Axios 和 Fetch API 都是用于在不重新加载整个页面的情况下与服务器进行通信的技术和库。它们在处理超时、终止请求、进度反馈等机制上有一些显著的差异。以下是它们的详细比较: 1. XMLHttpRequest (XHR) XMLHttpRequest 是一种浏…...

【HuggingFace Transformers】OpenAIGPTModel源码解析
OpenAIGPTModel源码解析 1. GPT 介绍2. OpenAIGPTModel类 源码解析 说到ChatGPT,大家可能都使用过吧。2022年,ChatGPT的推出引发了广泛的关注和讨论。这款对话生成模型不仅具备了强大的语言理解和生成能力,还能进行非常自然的对话,…...

macOS安装Java和Maven
安装Java Java Downloads | Oracle 官网下载默认说最新的Java22版本,注意这里我们要下载的是Java8,对应的JDK1.8 需要登陆Oracle,没有账号的可以百度下。账号:908344069qq.com 密码:Java_2024 Java8 jdk1.8配置环境变量 open -e ~/.bash_p…...

SpringBoot教程(安装篇) | Elasticsearch的安装
SpringBoot教程(安装篇) | Elasticsearch的安装 一、确定Elasticsearch版本二、下载elasticsearch(windows版本)官网下载如何解压配置 允许 别人跨域 访问自己启动运行 三、Es可视化工具安装(elasticsearch-head&#…...