进程(从操作系统的状态到linux的进程状态一步到位)

进程的概念

我们常见的计算机都遵循冯诺漫体系结构

当我们运行一个可执行程序的时候,开始程序会保存在磁盘上面,运行的时候,会加载到存储器上面,从而cpu进行处理。再返回存储器,再到输出设备。

为什么要先加载到存储器?

因为外设效率太慢,我们cpu不直接和外设打交道,要数据,只能从内存中读取。文件加载到内存上面是按需拷贝,然后cpu是读取地址,然后从内存上读取文件。

CPU 绝不直接等外设,必须让内存做缓冲。

程序运行之前,必须加载到内存。

CPU 不直接读外设,外设直接把数据丢进内存。

当我们在键盘输入泥嚎发送给朋友的时候,键盘小字节的内容直接拷贝加载到内存,

还有拉取文档给朋友,文档本身也在外设磁盘里面,加载 到内存,cpu读取,返回内存,再通过网络一系列发给朋友。

操作系统

什么是操作系统

操作系统是一个对软硬件管理的软件,它也是由c语言写的。

操作系统又分为广义操作系统(window操作系统加图形化界面+软件。linux加指令加shell命令行)

狭义操作系统☞的是操作系统内核。

为什么要有操作系统

操作系统对下进行软硬件管理(手段)。对上给用户提供良好的环境。

没有操作系统,计算机就无法正常的工作。

操作系统是如何管理的

操作系统对软硬件的管理。操作系统不能直接跟软硬件获取数据。要通过驱动程序获取数据,然后进行描述,在组织。

就像校长对于学生,不会当面一个从每个学生获取数据,而是通过辅导员来获取数据的.

先描述是什么?描述就是把被管理者的部分信息用结构体struct管理起来。为什么不用class(因为操作系统是用c语言写的)。

再组织是什么?就是对于每个个体,通过数据结构进行链接。完成对链表的增删查改。

(从而更好的管理,对于进程,我们可执行程序在磁盘硬件上,加载到内存,创建进程。进程就是对程序的描述,如何进行几个进程的组织,如果不执行该程序就会删除)

驱动就是翻译,操作系统和硬件之间的翻译。

什么是系统调用什么 是库函数

在开发⻆度,操作系统对外会表现为⼀个整体,但是会暴露⾃⼰的部分接⼝,供上层开发使⽤,
这部分由操作系统提供的接⼝,叫做系统调⽤。

系统调⽤在使⽤上,功能⽐较基础,对⽤⼾的要求相对也⽐较⾼,所以,有⼼的开发者可以对部
分系统调⽤进⾏适度封装,从⽽形成库,有了库,就很有利于更上层⽤⼾或者开发者进⾏⼆次开

为什么要有系统调用?因为直接让用户访问内核数据结构会存在安全问题。

系统调用也是唯一访问操作系统的接口。

我们使用的printf,等库函数也会封装系统调用,从而高效的访问操作系统。但并不是所有的库函数都有系统调用。

进程

进程的基本概念

进程在书本中被描述为加载到内存的就是进程。但真正的进程,是程序的属性被描述成take_struct,然后用数据结构链接起来。还有映射的代码。进程=内核的数据结构+程序的代码和数据。

进程是如何被管理的

对于程序,软件被操作系统加载到内存中,操作系统会把许多属性描述成为一个结构体放在内存。

它对于的代码(需要的时候才会映射)也会拷贝到内存。对于多个进程,操作系统是如果管理的,就是先描述,再组织。

take_struct内部描述的进程的属性。许多进程会被数据结构链接。所以操作系统对进程的管理变成了对链表的增删查改。

那进程内部的属性包含哪些:

标识符pid:: 描述本进程的唯⼀标⽰符,⽤来区别其他进程。

状态:任务状态,退出代码,退出信号等

优先级:对于cpu在调度的时候,进程相对于其他进程运行的优先级。

程序计时器:程序中即将被执行的下一条指令的地址。

内存指针:与程序代码和进程相关数据的指针。,还有和其他进程共享的内存块的指针
上下⽂数据: 进程执⾏时处理器的寄存器中的数据休学例⼦,要加图CPU,寄存器
I∕O状态信息: 包括显⽰的I/O请求,分配给进程的I∕O设备和被进程使⽤的⽂件列表。
记账信息: 可能包括处理器时间总和,使⽤的时钟数总和,时间限制,记账号等。
其他信息

对内部属性的认识

pid和ppid:表示自己进程的标识符和父进程的标识符。怎么查找了?getpid(),和getppid()

当前进程一般ppid都是bash,注意先执行完前一条命令,再执行后一条命令要用&&,head -1这个是数字1.下面那个是grep code的进程

可以通过这个方式查看当前进程pid和父进程的ppid。

还有函数getpid(),getppid()。

当结束程序的时候,进程也会消失。

进程里面的属性

还有每次重新创建进程的时候,pid都会不一样。

什么是cwd?

进程属性的cwd是什么,其实就是当前进程的路径。为什么要cwd这个属性,当我们在程序读写文件的时候,如果没有这个文件,会在当前路径创建文件。这个cwd就是缺省路径

修改路径:

把路径复制放在cwd的数组里面。char*bf是存放char数组,或者字符串。

创建子进程(frok)

问题一:为什么给子进程返回0,给父进程返回子进程的pid.

因为需要唯一的标识符来识别进程,未来还有一个父进程:多个子进程。

问题二:为什么fork会有两个返回值。

创建子进程,先会拷贝pcb成为子进程,修改部分属性,比如pid,ppid。

问题三:为什么同一个变量n==0,又可以大于0.

对于父进程和子进程他们的数据,子进程是拷贝父进程的pcb,代码是共享的,数据是分开的,这就是进程具有独立性。不仅子进程具有独立性,不同的进程更是独立。

不同一个flag,虚拟地址一样,但是物理内存空间不同,写时拷贝。

进程状态

操作系统的状态示意图。就让我们一一来里了解。

状态就是进程task_struct内部的一个属性。

运行状态

再了解运行状态的时候,我们来了解一个东西。cpu在调用进程的时候,会在调度进程,从cpu获取调度队列。为什么进程会被双链表链接,还有调度队列。我们c语言不是一个结构体只能一种数据结构链接嘛。

知道调度队列的结构体的地址,那我们怎么获取里面的数据了。首先c语言中,我们可以通过 字节最小地址的位置来偏移获取其他地址。对于int知道最小的地址,再偏移3个,然后cpu会根据当前的字节序组合成一个完整的整数类型。

对于我们只知道调度队列结构体的地址怎么知道进程的其他属性了?这就需要我们用一个思维,对于进程开始的地址肯定不是从零开始。那如果我们假设开始从零开始的,再算到成员结构体的偏移度,再从结构体的地址减去偏移度。

结构体的地址(即 &struct_obj)就是结构体第一个成员的最小字节地址。

所以啊,内核这样做更有通用性,一个task_struct就可以属于双链表,又属于调度队列,还有其他数据结构。

我们把在调度队列的进程叫做运行状态。

阻塞状态

就是进程等待某种资源的时候,资源 没有就绪,cpu会让当前进程阻塞住,直到资源就绪。

列如,我们执行输入的程序的时候,键盘没有被摁下,直到键盘被摁下,进程才从阻塞进程调到调度队列。

进程的成员有运行队列,等待队列,所以当进程阻塞的时候,运行队列断开啦,等待队列链接。device里面也有等待队列,但是头节点,用于连接进程中的等待队列。

当遇到scanf的时候,会遇到阻塞,所以会把进程连接到键盘device的等待队列后面。通过进程成员的等待队列的结构体连接。

阻塞挂起和运行挂起

什么是阻塞挂起,就是一个进程被阻塞了,当是内存空间严重不足,进程也没有运行,它的代码和数据占用空间,所以在磁盘开辟一个swap空间。把代码和数据拷贝过去。然后把内存中的删除。

什么是运行挂起,当内存还是不足的时候,一个cpu只能运行一个进程,所以在调度队列的其他进程的代码和数据也可以放在swap区,当需要的时候再换入进来。

对于没有修改的代码可以不放在swap()区,可以直接删除,需要的时候在从磁盘的源文件拷贝。

linux进程状态、

睡眠状态(slepping)

对于一个程序等待某种资源然后继续被cpu调用。等待的过程叫睡眠状态(s)可以被中断,crtl+c;或者kill -9;

暂停状态(T)

暂停状态就是进程不符合要求的工作,os会暂停进程。

在介绍暂停状态的时候,我们先了解什么是前台进程,什么是后台进程。一个终端只能有一个前台组。当然子进程属于父进程的组,所以子父进程都可以是前台进程。前台进程就是状态后面加一个+号。

要从键盘读取为前台进程,所以它的父进程bash就是后台进程了,所以pwd,ls -l等指令就没有用。crtl+c可以结束前台进程。

为什么要有前后台进程?

因为前台进程接受键盘的数据。后台进程不需要数据,也能跑提高效率。

fg加编号可以把后台进程转换为前台进程。

当我们用gdb调试的时候,遇到断点就暂停了,是因为系统让进程处于暂停状态了

不可中断状态(disk sleep)

对于这种状态,当我们大量的io操作的时候,磁盘老,硬件出现故障的时候,就会出现这种状态持续永久。对于平常大量io的时候只会出现短暂的d。对于出现d 状态,如果长时间出现那么会出现坏盘等操作,因为d状态不能杀死。还会进行io操作。

僵死进程

对于僵尸进程是因为一个pcb进程因为进程完成结束或者进程退出。代码和数据会被回收,但是pcb里面的

会等着父进程来读取。如果父进程一直不来读取,进程会处于僵尸状态。进程都会有父进程。

如果进程没有被读取就会出现内存泄漏。因为pcb进程没有被读取。回收.

对于进程结束里面的malloc和new操作进程结束不会出现内存泄漏。但是对于一个软件都会死循环,我们如果没有malloc和free,不管是是前台进程还是后台进程一直malloc都会造成严重的内存泄露。所以我们要free和delete.

为什么linux没有单纯挂起状态?

因为对于可运行状态内存不足被交换到swap区,和等待某种资源,如键盘的输入。这种也会交换到swap区他们都是T状态.

孤儿进程

对于上面子进程退出,父进程没有来读取就会出现僵尸进程。对于孤儿进程则是子进程退出,父进程没有退出。父进程退出了,子进程还在。怎么办?

孤儿进程会pid为1的领养了之后。会变成后台进程。所以只能kill -9加pid来杀死进程。

被领养就是为了pcb里面的信息被读取,pcb不被读取。避免内存泄露。

相关推荐
A小辣椒13 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒17 小时前
TShark:基础知识
linux
AlfredZhao19 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao1 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5202 天前
Linux 11 动态监控指令top
linux