进程可以简单理解为跑起来的一个个程序,就比如你现在在阅读我的博客,那么你正在使用的CSDN或者是浏览器就是一个进程.
.exe叫做可执行文件,这些可执行文件都是静静躺在硬盘上的文件,双击之前
没有任何影响,一旦双击执行exe文件,操作系统就会把exe加载到内存中,并且
让CPU执行exe内部的一些指令,exe里面就存了很多这个程序对应的二进制指令 ,之前我们稍微说过冯诺依曼体系,这是我们理解操作系统的基础.
当exe执行起来,不躺了,开始进行具体的工作,变成动态的了,我们把运行起来的可执行文件称为"进程".
通过任务管理器,我们可以看到好多好多进程,所以当你迷茫的时候,不清楚进程的时候打开任务管理器,会有惊喜!!
1.先描述一个进程(明确出一个进程上面的一些相关属性).
操作系统里面主要通过C/C++来实现,此处的描述就使用C中的结构体(像Java类).都是编程语言中提供的自定义类型,结构体功能更简单,操作系统中描述的这个结构体,称为"PCB"(process control block)进程控制块
2.再组织若干个进程(使用一些数据结构,把很多描述进程的信息放到一起方便增删改查)典型的实现,就是使用双向链表来把每个进程的PCB给串起来.
创建进程:先创建出PCB,然后把PCB加到双向链表中,
销毁进程:就是找到链表上的PCB,然后删除,
查看任务管理器:就是遍历链表,
进程的身份标识,就是进程的身份证
指明了这个进程要执行的代码/指令在内存的位置,以及这个进程执行中依赖的数据的位置.
当运行一个exe,此时操作系统就会把这个exe加载到内存中,变成进程 (进程要执行的二进制指令(通过编译器生成),还有一些重要数据)
程序运行过程中,经常要和文件打交道(文件在硬盘上的)操作文件就是在操作硬盘
我们很直观地就可以感受到,想要马儿跑就要给马儿吃草,你操作系统想要进程工作,必然要给我们的进程分配系统资源.
进程调度:现在的操作系统一般都是"多任务操作系统"(前身单任务操作系统),
一个系统同一时间执行了很多的任务
系统上任务(进程)的数量有很多,但是CPU核数就几个,让有限的核心能够执行
很多的进程,这就是"进程调度"
并行:微观上,两个CPU核心,同时执行两个任务的代码
并发:微观上,一个CPU核心,先执行进程一,然后二然后三…然后一
只要切换到足够快,宏观上看起来,就好像多任务在同时执行
并行和并发这两件事只有在微观上有区分,宏观上我们区分不了,微观上的区分
都是操作系统自行调度的结果,有可能是并行,有可能是并发,有可能两个一起
正因为在宏观上区分不了并行并发,我们在写代码的时候也不去具体区分这两
个词,实际上通常使用"并发"这个词来代指并行+并发.
我们只有在研究操作系统进程调度的时候,稍做区分,其他就使用并发作为统称.
时间管理大师:A rich B handsome C dog
通过一张时间表,安排好时间,避免同一时刻三个人碰面
宏观上看来, 我谈了三个,微观上看来,同一时间我只和一个对象在一起
并发,规划时间的过程,也就是"调度"的过程
下面我们讲的这一组特性,不同于进程本身的pid,内存指针,文件描述符表这三个,而是我们在调度进程时需要知道的特征!
描述了当前这个进程接下来应该怎么样调度:
就绪状态:随时可以去CPU上执行
阻塞/睡眠状态:暂时不可以去CPU上执行
Linux中的进程状态还有很多
正常情况下ABC都是随叫随到的,这就叫做就绪状态
假设A要出差一个月,就认为A是阻塞/睡眠状态,这样的进程就不进行调度
先给谁分配时间,给谁分的多
我最喜欢B其次是A最后才是C
这是我在排时间表的时候,优先给B
周一到周三给B周四周五和A周六和C周天休息
统计了每个进程都分别被执行了多久,都执行了哪些指令,分别排队等了多久
给进程调度提供指导依据的,
如果长此以往,和C时间太少,C的好感度就不高了,根据本子上排的时间发现
给C的时间太少了,接下来适当给点甜头
就表示了上次进程被调度出CPU的时候,当时程序的执行状态,下次上CPU的时候
就可以恢复之前的状态,然后继续往下执行.
进程被调度出CPU之前,要先把CPU中所有的寄存器中的数据都给保存到内存中
(PCB的上下文字段中),相当于存档了,下次进程再被调度上CPU的时候就可以
从刚才的内存中,恢复这些数据到寄存器中
就是存档和读档,存档存储的游戏信息就是"上下文"
A说让我做点准备买点泳衣B让我准备礼物,过了几天A问我的时候,我给记混了
怎么区分开?记到小本子上,把每次约会的信息记录下来,下次见面的时候就可以
延续上次约会的状态
这样的故事在操作系统中无时无刻不在发生
进程的调度,其实就是操作系统在考虑CPU资源该如何给各个进程分配
内存资源又是如何分配的呢?
虚拟地址空间
由于操作系统上同时运行着很多个进程,如果某个进程出现了Bug,是不会影响
到其他进程的,是"进程的独立性"保证了这一点,依仗了"虚拟地址空间"
如果某个居民阳了,是否会影响到其他的居民?
一旦发现有人阳了,就需要立刻封楼封小区,否则其他人也有危险
这个情况就类似于早期的操作系统,早期的操作系统,里面的进程都是访问同一个
内存的地址空间,如果某个进程出现了Bug,把某个内存的地址给写错了,就可能
引起其他进程的崩溃
解决方案就是把这个院子,给划分出很多的道路,这些道路之间彼此隔离开,每个
人走各自的道路,这个时候就没事,此时即使有人确诊,也影响不到别人
如果把进程按照虚拟地址空间的方式给划分出很多份,这个时候虽然每一份只有
一丁点,虽然系统有百八十个进程,但是实际上从微观上看,同时执行的进程只有
几个,其实每个进程能够分到的内存还是不少的,而且另一方面,进程也不是所有
的进程都用那么多内存,有的内存大,大多数进程也就是M的量级
只要保证划分出来的道路能够满足同时下楼的人数即可.
虽然我们进程是有独立性的,但是不可能一台电脑上所有进程之间都是老死不相往来的态度,人是社会性生物,我觉得计算机同样如此,就比如我可以在QQ里面打开别的程序,这难道不能算是进程间的一次交互嘛?
我们的两个进程之间,也是隔离开的,也是不能直接交互的,操作系统也是提供了
类似的"公共空间",进程A把数据先放到公共空间上,进程B再取走
进程间通讯
操作系统中,提供的"公共空间"有很多种,各有千秋,有的存储空间大,有的小
有的速度快,有的慢
操作系统中提供了很多种这样的进程间通信机制(有些机制属于历史遗留,
已经不适合于现在的程序开发)
现在最主要使用的进程间通信方式有:
1.文件操作
2.网络操作(socket)
好了,希望我的这篇博客可以解决您对于进程的一些困惑!
百年大道,你我共勉!!