文章目录
1. 理解调用(11-0.00.00)
1.1 例子讲述
- 系统调用:操作系统要向上提供对应的服务,但是操作系统不相信任何用户或者人。这里可以用操作系统类比于银行举个例子
- 这里拿银行的工作原理进行阐述:比如客户它要去银行存钱,银行会让客户直接进入到后端,将钱放进去或取出来,肯定不会啊
- 谁知道你有没有去修改数据。所以银行就提供了一个个小窗口来阻拦客户,你就只能通过身份证在这个窗口办理服务,那这个银行就是咱们所说的操作系统,而这个窗口就相当于系统调用的接口
- 这里再简单理解一下系统调用:无论是
Linux/windows/macos
都是C语言写的,所以一般提供给我们的系统调用就是C风格的C函数 - 该函数基本会包括输出参数和返回值(输出参数:用户给操作系统的数据。返回值:操作系统给用户的数据),那操作系统它的本质就是:用户和操作系统之间,进行某种数据交互。
- 这样用户和操作系统的耦合度就比较低了,操作系统就能在保证自身的安全前提下提供服务
- 那有的时候银行窗口外面可能会存在一个人(大堂经理),其实这个大堂经理也是银行系统体系的一部分,这个大堂经理就相当于别人提供给我们使用的库,外壳,指令,它们的底层全部都是直接或间接地去调用系统调用接口
- 库函数和系统调用属于上下层的关系,那如何知道库函数它的底层有没有调用系统调用呢?现如今是很难进行判断的
- 不过有一个简单的判定方法,就是你去调用库函数时有没有去访问硬件,只要它访问了硬件,必定会去访问系统调用(比如文件操作:
fscanf, fprintf
,网络操作等)
1.2 专业术语
- 在开发⻆度,操作系统对外会表现为⼀个整体,但是会暴露⾃⼰的部分接⼝,供上层开发使⽤,这部分由操作系统提供的接⼝,叫做系统调⽤
- 系统调⽤在使⽤上,功能⽐较基础,对⽤⼾的要求相对也⽐较⾼,所以,有⼼的开发者可以对部分系统调⽤进⾏适度封装,从⽽形成库,有了库,就很有利于更上层⽤⼾或者开发者进⾏⼆次开发
2. 进程
2.1 基本概念-专业术语
- 课本概念:程序的⼀个执⾏实例,正在执⾏的程序等
- 内核观点:担当分配系统资源(CPU时间,内存)的实体
2.2 描述进程-PCB
基本概念
- 进程信息被放在个叫做进程控制块的数据结构中,可以理解为进程属性的集合
- 课本上称之为PCB(
process control block
),Linux操作系统下的PCB是:task_struct
task_struct
→PCB的⼀种- 在Linux中描述进程的结构体叫做
task_struct
task_struct
是Linux内核的⼀种数据结构,它会被装载到RAM(内存)⾥并且包含着进程的信息
- 在Linux中描述进程的结构体叫做
- 问题:这些程序在内存的什么地方加载呢?这个代码和数据有没有被CPU已经执行完了呢,这个代码和数据所占的空间要被释放了,这些程序有没有可能需要停止运行一下?空间可能不够了需要再去扩容?
- 程序加载到内存的有这么多的问题,操作系统要对这些程序做管理,但是能
直接
做到?是做不到的,比如一个程序的代码和数据在操作系统的视角中,是哪个进程的代码和数据? - OS就只知道这个程序有代码和数据但并不知道是哪个进程的,所以操作系统必然是要对这些加载到内存中的可执行程序做管理!那如何做进行管理呢?这里就需要用到
PCB
,也就是先描述 - 这个
PCB
是操作系统对内核数据结构对象的统称(那PCB
就包含Windows,Linux,macOS
下的内核数据结构对象),在Linux
下具体就是struct task_struct
。这两者的关系就是抽象和具体的关系,比如PCB
就相当于媒婆,而struct task_struct
就相当于王婆,具体到哪个媒婆
2.3 简历例子
找工作,每一个人都需要做一份简历,给对应的公司投递简历,那这个公司的HR就会收到一堆简历,就会将这些简历给筛选出来给面试官查看。这是故事背景
- 首先你要找工作,本质上并不是你在找工作,是你的简历在找工作
- 你投了简历在一家公司,HR告诉你目前在排队当中,并不是你这个人在排队,是你的简历在排队
- 你的简历本质上不就是对你自己做先描述吗?包括你的技能信息,个人评价,荣誉项目等等
- 把简历投递给HR就相当于把你这个人的属性推送给HR,而面试官则会拿着这简历依次去面试一个一个的人
- 那这个面试官就相当于
CPU
,面试官拿出来的一份一份的简历就当于一个队列,你的简历就相当于PCB
,你就是加载到内存中的可执行程序 - 面试官进行淘汰,筛选操作,并不是针对于你这个人,而是你的简历
- 所以当一个可执行程序加载到内存当中,它自己反而是最不重要的,最重要的是操作系统会去创建一个PCB去描述它
2.4 task_struct 的属性(先了解)
- 标⽰符: 描述本进程的唯⼀标⽰符,⽤来区别其他进程
- 状态: 任务状态,退出代码,退出信号等
- 优先级: 相对于其他进程的优先级
- 程序计数器: 程序中即将被执⾏的下⼀条指令的地址
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下⽂数据: 进程执⾏时处理器的寄存器中的数据[休学例⼦,要加图CPU,寄存器]
- I/O状态信息: 包括显⽰的I/O请求,分配给进程的I/O设备和被进程使⽤的⽂件列表
- 记账信息: 可能包括处理器时间总和,使⽤的时钟数总和,时间限制,记账号等
- 其他信息
3. 查看进程的操作
3.1 getpid
- 先明白一点:我们历史上执行的所有的指令,工具,自己的程序,运行起来全部都是进程
getpid
是个系统调用,可以用来查看进程ID。可以通过man手册查看:man 2 getpid
- 可以写一段死循环获取进程ID的代码,方便进行查看该进程信息
- 命令:
ps ajx | head -1;ps axj | grep code(可执行程序名)
。分号:执行两条命令(先是前面的命令),可以用&&
来代替。分号前面的命令→查看各列所代表的含义,分号后面的命令→查看特定进程信息。这里开两个xshell
,登录一个账号即可
grep --color=auto ./code
它是高亮,它也是个进程,包含了关键字./code
,所以会显现出来。可以在./code
后接着输入:| grep -v grep
,选项v
反向匹配,包含grep
就不显现- 输入命令:
kill -9 31547
,可以将特定进程给杀掉。之前的ctrl + c
强制停止实质上是杀掉进程的
3.2 proc 目录
在Linux中,我们用户是以进程的方式去访问操作系统的,可以将用户看成老师,而操作系统就是学生。创建进程就是给学生布置任务,按照自己的要求去完成任务
ls /proc
:通过文件的方式去查看进程。操作系统不仅能让用户通过ls命令去查看磁盘上的文件,还能将内存中的相关数据也以文件的方式给呈现出来,让用户能动态的看到内存中的相关数据。
像proc
就是一个内存级的文件系统,它跟磁盘就没有半毛钱关系,所有的数据都是内存中的数据
proc
目录里记载着当前系统中所有进程的相关信息,该目录下的所有文件,每一个数字目录代表着特定进程的PID,里面的内容包含着进程运行时的动态属性,如果进程退出,该目录会被系统自动移除
如果你在这个程序运行时,将这个可执行文件删掉以后,进程仍然在继续跑。原因是你删掉的是磁盘上的可执行文件,当进程启动时,这个文件已经被拷贝到内存中了,你将其删掉并不会直接影响这个进程(后续可能会影响)