Linux进程概念
- 冯诺依曼体系结构
- 操作系统
- 操作系统是什么
- 操作系统与硬件的关系
- 操作系统如何管理硬件数据
- 操作系统与软件的关系
- 操作系统的安全
- 操作系统的服务
- 系统调用和库函数概念
- 进程的基本概念
- 什么是进程
- 如何查看进程
- 进程常见的调用
冯诺依曼体系结构
常见的计算机(台式,笔记本),与不常见的计算机(服务器)大部分都遵守冯诺依曼体系结构。
输入设备就是现在用的鼠标键盘等等,输出设备就是音响,屏幕等等。
存储器是什么呢?是内存,内存有一个坏处就是掉电易失,并且不能永久存储内部的数据,在玩一些单机游戏的时候都提示过如果不存档会丢失数据,这就是放在了内存里。
如果想永久保存某些数据,存档那种操作,就要放在磁盘里,磁盘是外部储存,拥有永久性储存能力,他是一个外设,
为什么叫外设呢?这是因为与CPU作比较才被称为外设,外设有很多种,鼠标键盘显示器等等全都是,外设分为输入设备与输出设备,也有同时拥有输入输出功能的外设,例如网卡和磁盘。
CPU
CPU = 运算器+控制器+其他
CPU其实是一个很被动的硬件,他不会去主动的找东西去进行计算,只会执行我们给的指令。
那么CPU执行命令的前提是它要认识这条指令才行,帮助CPU认识的东西叫做指令集,这个东西就在CPU内部,就像人的大脑拥有知识一样能通过所了解的知识分析各种事务。
在写完一个程序的时候会进行编译,让他转换成二进制可执行程序,这就是让CPU读懂你指令的一个过程。
那么CPU是从哪里找指令的呢?
有一个概念叫做木桶原理,说:水桶里面能装多少水取决于最短的地方在哪里。
CPU也是同样的,如果从磁盘中拿数据读取运行,效率会非常慢,但是从内存中读取运行整体效率就提高了。
内存中的内容是从磁盘中读取的,然后到在送到CPU中,CPU工作完之后会在放入到内存中,经过一系列操作该还给磁盘就放入磁盘当中,我们可以把内存当作一个很大的缓存。
那么磁盘怎么知道该把什么内容放进内存中呢?内存又怎么知道什么东西不用还给磁盘呢?这都是操作系统的功劳。
结论:
在数据层面:
CPU不直接与外设有直接联系,只和内存有直接联系。
所有外设载入的数据都只能放入内存中,内存写入只能是写道外设中。
当我们用QQ发消息给朋友的时候,大概是一个什么样子的操作呢?
从你键盘输入“你好”两个字,然后送到内存中,这个时候因为你们同时打开了QQ这个软件,所以内存中就都有QQ程序的代码,CPU在对QQ这个代码进行操作,你发的消息会在QQ程序中进行加密然后传到网卡和你的显示器上,再通过网络传输传到你朋友电脑的网卡上,然后放到内存中,同样是CPU操作QQ程序代码进行发过来的消息进行解密,最后在放到他的显示器上。
操作系统
操作系统是什么
操作系统是一个对软硬件做资源管理的软件。
合理的管理软硬件资源为用户提供更稳定,高效,安全的环境。
操作系统与硬件的关系
在学校中,整个学校归校长管,校长就是管理者,学校的学生就是被管理者,但是我们发现平时校长很少亲自查看或者督促我们做什么事情,都是导员或者班主任来管理。
那么学校有很多的学生,校长是如何知道每个学生的个人信息并且进行管理的?入校的时候我们都会将自己的个人资料交给校方,平时的考试成绩和测试成绩也是,我们所有的数据都交给了学校,所以校长是通过数据对我们进行管理的。(管理的前提是要先整理拿到的数据)
那么对于成绩不合格的同学会进行留级不发放毕业证,严重的会被开除,这是由校长这个管理者决定的,也就说明管理者有决策权,开除这个学生校长会让其他人去执行。
也就是说管理的本质就是对数据进行管理,虽然我们不和校长打交道,但是我们的信息时时刻刻都在校长手里。
在计算机中也是一样的,操作系统是管理者,硬件是被管理者,操作系统通过驱动来管理我们电脑的硬件:
操作系统通过驱动来拿到硬件的数据。
操作系统如何管理硬件数据
继续学校这个话题,学校学生多,用特殊的软件去管理会更好,比如说:
定义一个学生的结构体>姓名,年龄,身高,体重,成绩,联系方式等等…
然后将他们的个人信息用链表进行关联,这个时候就可以全方面的管理学生,比如A学校和B学校进行篮球比赛,A校长和B校长首先会进行学生信息开始查找,以180身高为标准照学生;或者学校找应该被开除的学生,顶一个标准,留级不能超过三次,那么在这个链表中找到异常的学生就会将他直接踢出去。
也就是说,想要管理学生,收据学生数据信息,然后先描述(学生的姓名,年龄等等…),然后再进行组织(链表连起来学生信息),这个就是管理的基本逻辑。
那么计算机也是同样的道理,硬件有很多种类,先知道硬件都有什么,然后再用每个驱动分别管理相对应的硬件,再通过特殊的方式连接起来。(也就是结构体与数据结构的关系)
如果键盘数据有异常,操作系统就会将键盘管理的结构体从链表踢出,然后管理没有异常的硬件就可以了。
也就是说操作系统只需要管理硬件对象中的数据就可以了。
操作系统与软件的关系
这次用银行举例,一个银行里面有文件,电脑,桌椅等物品,这些东西需要各个部门来进行管理与操作,银行行长能管理各个部门,那么行长下面也有经理之类的职位,经理同样也能管理各个部门,但是他们又受行长的管理。
行长是管理者角色,也就是操作系统,各个部门是执行者,驱动,电脑,桌椅文件等是硬件,那么经理等人呢?
我们可以看作是一个软件,软件也会控制驱动在控制硬件去做一些事情,但是软件也在被操作系统管理着。
操作系统的安全
我们都知道银行是一个很容易被不法分子盯上的地方,所以会设置层层安保措施,
可能有些人是好人不会做违法行为,但是不敢保证每一个都是好人,并且鉴别一个人是好是坏成本特别高,所以银行选择谁也不相信,一视同仁。
同样操作系统也是谁都不会相信,万一你把操作系统搞坏了,或者是驱动也坏了只剩下硬件,这就没办法在使用电脑了,甚至万一高功率让硬件损坏,那么就要重新买硬件组装或者换一台电脑。
银行不仅仅要保护自己还要对外提供服务,这怎么办呢?
去银行办理业务的时候,你需要排队,然后到做到窗口前,这时候你会发现你前面隔着玻璃,只露出来了一个小窗口:
操作系统同理,不仅要及保护自己也要对用户提供各种服务。
操作系统与银行窗口类似的就是操作系统接口(别称系统调用),因为操作系统都是C语言写的,那么接口时操作系统提供的,也就是说这个接口是C式接口。
接口本质就是操作系统通过C语言给我们提供的函数调用。
以后我们任何想访问硬件的操作都是要经过操作系统的帮助,我们只是输入了指令而已,其他事情是操作系统帮忙做的。(实际上是我们调用函数从而调用了系统的功能)
操作系统的服务
如果是一个老人不太懂银行的规定/流程和业务就需要问服务人员,在银行中会有大堂经理那种人来服务不懂的流程或者一些业务的客户。
同理如果我们上来就只能看代码去调用各个接口也是不懂,这时候就需要一个大堂经理来帮助我们,比如shell,数据库,界面等等。
这样我们指令,编程,还有其他操作就会很简单了。
之前编程写的第一个程序就是将某些内容打印到屏幕上,其这就等于通过操作系统,让操作系统帮助你将你的内容打印到了屏幕(硬件)上。
其实我们的每一个举动几乎都在让操作系统去帮助你控制计算机的各个硬件!这就是操作系统!
系统调用和库函数概念
在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
进程的基本概念
什么是进程
首先我们要知道,程序是在硬盘中的,想要运行这个程序就要放入内存中,然后通过CUP进行运作。
那么这么多程序加载进来怎么办呢?
这个时候操作系统就会通过PCB进行管理:
上面说了,管理首先要描述,然后组织。
PCB会进行结构体定义,这里也叫进程控制块:
struct task_struct
{
//进程该的属性
//进程对应的代码和地址
struct task_struct* next;
};
如果想要控制一个进程就需要定义一个结构体,定义出来的结构体指向一个进程的地址来进行控制,然后通过链表方式连接起来,这样就能很好的管理每个进程了:
操作系统如果想结束一个进程就会通过控制模块找到该进程的地址然后先释放掉这个进程在释放掉该程序对应的模块。
也就是说,对于进程的管理变成了对进程对应的PCB进行管理。
struct task_struct 是一个系统给我们PCB的内核结构(用来描述进程),需要创建内核变量,将该结构与进程的代码与数据关联,最后进行组织工作。
进程 = 内核数据结构(task_struct)+ 进程对应的磁盘代码
出现PCB是因为管理的核心思路就是先描述,再组织。
如何查看进程
先创建一个文件:
这就是一个进程了:
查看方法是:
ps ajx | grep ‘mypro’
ps ajx 是显示系统中所有进程的命令
第一个才是现在跑的进程,第二个进程是自己,因为在过滤进程的时候自己也是个进程,所以就把自己过滤出来了。
这些东西是什么意思呢:
ps ajx | head -1
这时显示标题:
那么这样会更好:
ps ajx | head -1 && ps ajx | grep ‘mypro’
意思就是先打印标题再显示进程内容
PPID:父进程ID
PID:进程ID
PGID:组进程ID
SID:会话进程ID
TTY:对应的终端ID
TPGID:线程组ID
STAT:进程状态
UID:用户ID
COMMAND:代表进程
如果想让这个进程停下来怎么办:
kill -9 PID
那么刚才进程在跑的时候是什么 ?
是CPU执行进程内部的所有代码,从开始到结束可能会有很长的时间,也就是说:
进程在调度的时候具有动态属性。
与进程有关的系统调用
这就是返回调用进程的pid,返回值相当于整数。
还有另一种查看进程的方式:
这种方式不是很常用:
ls /proc
这是查看内存的文件,蓝色的是进程pid,也是进程在内存的文件:
进入之后还能查看到这个进程的很多属性。
进程常见的调用
那么父进程 ID是什么呢?
因为进程每次都要进行随机分配地址,所以ID是变的,可是父进程ID没有变。
那我们查看一下父进程是什么:
这时候发现父进程是一个叫 -bash 的进程,他是一个命令行处理器,那么在处理这个程序的时候创建了一个子进程来运行这个代码,这是为什么呢?因为如果bash进程亲自运行但是报错就会停止工作,bash都停止工作了,我们后续想继续用Linux系统就无法正常使用了。
初始fork函数
然后再来看看fork函数,这个函数会颠覆语言方面的认知,因为这是系统方面的。
他说作用是创建一个子进程,并且有两个返回值。
很奇怪,之前学C/C++语言的时候从未听过如此离谱的话,现在写一个来测试一下。
其实大概是这个样子的:
这就是说等于两个程序在运行,只不过创建出来的子进程是从fork函数之后开始运行的。
总结:fork后续的代码父子进程共享,通过返回值的不同,让他们各自执行同一段代码。