【Linux】进程概念

秦jh_ 2024-08-31 13:07:02 阅读 71

    🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343

🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12625432.html

9efbcbc3d25747719da38c01b3fa9b4f.gif

目录

冯诺依曼体系结构

操作系统 

概念 

 设计OS的目的

结构示意图(不完整)

理解"管理"

系统调用和库函数概念 

进程

基本概念

描述进程-PCB

task_struct-PCB的一种 

进程状态查看

task_ struct内容分类 

通过系统调用获取进程标示符 

终止进程

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

fork返回值 

组织进程


前言

💬 hello! 各位铁子们大家好哇。

             今日更新了Linux的进程内容

🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

冯诺依曼体系结构

输入设备:键盘、鼠标、话筒、磁盘、声卡...输出设备:显示器、声卡、磁盘 ....中央处理器(CPU):运算器和控制器存储器:内存

存储器可以预先把输入设备的数据放入到存储器中,预先加入的数据可以预先进行计算,计算好的数据也可以先放到存储器中,等到输出设备需要时,再输出。这样就提高了效率。如果没有存储器,输入设备直接到cpu再到输出设备的话,由于输入、输出设备的速度很慢,效率就很低,尽管cpu的速度很快(木桶效应)。

结论:

cpu不和外设直接打交道,cpu只和内存打交道。外设(输入和输出)的数据,不是直接给cpu的,而是要先放入内存中。 

操作系统 

概念 

任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。 

操作系统是进行软硬件资源管理软件。 

广义的认识:操作系统=内核+外壳周边程序

狭义的认识:只是操作系统的内核。

 设计OS的目的

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

结构示意图(不完整)

每一种硬件都有对应的驱动层,驱动层是一套软件。驱动层向操作系统提供通信接口,使OS能通过驱动程序访问硬件,对其进行管理。有了驱动层,就不怕更换硬件时,由于硬件的厂商不同,导致OS无法管理了。 

理解"管理"

举例:

学校里面有校长、辅导员、学生。校长是管理者,学生是被管理者。校长不会直接与学生接触,校长管理学生只需要拿到学生的数据即可。校长关心的是学习相关的和基本信息,不关注你喜欢吃什么。校长关心的是学生,而不是某个人。学校人多,管理起来难,通过列表格的形式,管理学生的数据。这就相当于c语言里的结构体类型。为了让这些信息都连接起来,就需要通过链表或者其他高效的数据结构链接。当需要找数学成绩最好的学生时,通过查找数学成绩,找到某个结构体对象,就可以知道这个学生的全部基本信息。

 任何管理都是:先描述,再组织。

比如:C++和STL,C++的封装就是先描述,STL就是组织。

总结:

计算机管理硬件:

描述起来,用struct结构体组织起来,用链表或其他高效的数据结构 


用户不能直接访问硬件,硬件由OS管理着。而用户又不能直接访问OS,因为OS里面有重要的数据,所以OS就必须提供一个系统调用接口,用户通过系统调用方式使用操作系统。

打个比方:在银行,客户通过柜台窗口进行存取钱服务,而不是到了银行直接进去银行的系统自行修改数据。 

系统调用和库函数概念 

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

打个比方:来银行办事的人可能是大爷,大爷不知道流程,就会有老人通道进行辅助。这个通道就相当于库,入门的程序员就可以通过库来进行系统调用。

不同的操作系统的系统调用可能会不同,但有了库,即使底层的代码不同,都可以通过相同的函数名调用,比如C语言和C++的标准库,都可以用printf打印。 

进程

可执行程序没被运行前,是存在磁盘中的。运行后,程序的二进制代码和数据就会加载到内存中。由于进程可以同时有很多个,就有哪些进程的优先级高等问题,所以在内存中的代码和数据不是进程。OS需要管理很多进程,所以就会有结构体PCB进行管理。每一个进程都有一个PCB。进程=PCB+自己的代码和数据。

基本概念

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

描述进程-PCB

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

task_struct-PCB的一种 

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

举例:每个人的简历到了hr的手上,每个人是一个实体,而简历就相当于 task_struct 。OS看的是task_struct,而不会直接看代码和数据。

进程=内核task_struct 结构体+程序的代码和数据。

调度运行进程,本质就是让进程控制块task_struct进行排队。 

进程状态查看

ps aux / ps axj 命令 

如果想查找某个进程的状态,可以使用grep。

可这样就看不到开头第一行的说明了。所以还可以使用&&进行连接,表示同时执行该指令。

&&左右两边执行完再进行合并。

还可以通过 /proc 系统文件夹查看:

我们运行程序后,通过/proc系统文件夹查看,存在该pid命名的文件夹,里面存的就是文件的属性信息。

exe是可执行程序,也就是说我们刚刚的进程是在这个路径下的process加载形成的。

如果我们把这个可执行程序干掉了,如下图 

我们发现程序还在运行,如下图:

原因:因为程序已经运行了,我们删掉的是磁盘的可执行程序。而内存中的还在。


 

 上方中的cwd,指的是进程的当前工作路径。

每个进程在启动的时候,会记录自己当前在哪个路径下启动。

我们把进程跑起来后,它会在当前的工作路径下生成log.txt文件。

如果我们想改变进程的工作路径,需要使用chdir

我们将进程跑起来,

 

发现工作路径确实被更改了。

创建的log.txt文件也在该路径中。

task_ struct内容分类 

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

通过系统调用获取进程标示符 

PID就是进程的唯一标识符。系统有提供接口来给我们查看。我们通过man getpid 指令查看

使用getpid()时需要包<unistd.h> 和 <sys/types.h> 两个头文件。pid_t 就是无符号整形。

getppid()就是获取当前进程的父进程的id。

上图中,左右两边PID对应得上。

由上图可知,进程每次启动,对应的pid都不一样,这是正常的。但是为什么父进程的ppid都是一样的?

可以看到,bash就是父进程。还记得之前讲过的,shell是媒婆,bash是王婆。bash会创建很多个子进程。

终止进程

ctrl+c是在用户层面上终止进程。

kill -9 pid 可以用来直接杀掉进程。 

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

通过man fork 指令来认识fork。fork的作用就是创建一个子进程

父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)

while :; do ps axj | head -1 && ps axj | grep myprocess|grep -v grep;sleep 1;done

 通过上方指令,我们可以不停打出进程的状态。

运行后如下图:

按照代码的逻辑,后面多出了一个子进程。fork之后,父子代码共享。所以打印了两次hello world。

fork返回值 

fork会放回两个值,如果创建成功就会返回子进程的pid给父进程,并且返回0给子进程。如果创建失败,就会返回-1。 

fork 之后通常要用 if 进行分流 ,如下图:

  fork有两个返回值,其实是在fork函数内部创建子进程的时候,子进程已经创建完成了,才到return ,这时候就就是父子进程各自return了。

父子进程具有独立性,互不影响。

创建多个子进程

组织进程

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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。