Bootstrap

Linux:进程的概念

一、 冯诺依曼体系结构

计算机硬件上的结构:
在这里插入图片描述
输入设备:键盘,鼠标,话筒,摄像头……网卡,磁盘
输出设备:显示器、磁盘、网卡,打印机……
输入/输出设备称为外设,Input/Output->IO,站在内存的角度理解IO

CPU = 运算器 + 控制器

存储器:内存
磁盘是外部存储

二、操作系统(Operator System)

1、概念

任何计算机系统都包含⼀个基本的程序集合,称为操作系统(OS)。
操作系统一款进行软硬件管理的系统软件。
操作系统包括:
• 内核(进程管理,内存管理,⽂件管理,驱动管理)
• 其他程序(例如函数库,shell程序等等)

在这里插入图片描述

2、设计OS的目的
  • 操作系统向下对软硬件资源管理。(不是目的,是手段)
  • 操作系统对上,为用户程序(应用程序)提供一个良好的执行环境。(目的)
    在这里插入图片描述
  • 软硬件体系结构是层状结构
  • 访问操作系统,必须使用系统调用——其实就是函数调用,只不过是系统提供的
  • 我们的程序,只要你判断出它访问了硬件,那么它必须贯穿整个软硬件体系结构
  • 库可能在底层封装了系统调用

操作系统核心:管理(先描述,再组织)

3、系统调用

操作系统要向上提供对应的服务
操作系统,不相信任何用户

用户不能直接访问操作系统内部的信息,必须通过系统调用返回信息。

三、进程的基本概念与基本操作

1、概念
  • 课本概念:程序的一个执行实例,正在执行的程序等。

  • 内核观点:担当分配系统资源(CPU时间,内存)的实例。

  • 进程 = 内核数据结构对象 + 自己的代码和数据

2、描述进程——PCB
  • 进程信息被放在⼀个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
  • 课本上称之为PCB(process control block),Linux操作系统下的PCB是:task_struct
  • 进程的所有属性,都可以直接或者间接通过进程控制块找到

在linux具体的进程:

  • 进程 = PCB(task_struct) + 自己的代码和数据
3、task_struct

在这里插入图片描述

4、getpid 获取进程ID

谁调用这个函数就获取谁的进程ID
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、ps axj 所有的以特定格式的进程

在这里插入图片描述

也可以使用 top 命令来查,但查看全部太多了不方便我们看

只查看当前我们的进程:
在这里插入图片描述
显示进程对应的信息:
在这里插入图片描述
连续执行两条指令,用分号依次隔开:
在这里插入图片描述

也可以使用 && 隔开两条指令,效果跟分号一样
在这里插入图片描述

6、kill - 9 + pid 杀掉进程

-9是信号
在这里插入图片描述

7、ls /proc 通过目录结构查看进程

在这里插入图片描述
对应的每个数字目录都是一个进程,数字对应的是进程的pid
目录里面存的是进程对应的各种属性
在这里插入图片描述
cdw(current work dir) : 存放当前路径
exe :存放可执行程序所在的路径

函数 chdir修改当前路径
在这里插入图片描述

8、getppid 获取父进程

Linux系统所以的进程都是被它的父进程创建的
一个父进程可以有多个子进程,进程也是进程树
在这里插入图片描述

在这里插入图片描述
-bash是命令行解释器:本质也是一个进程

  • OS会给每一个登录的用户,分配一个bash(-bash代表远程登录)!
9、fork创建子进程

在这里插入图片描述
在这里插入图片描述
本来是一个执行流的遇到fork会变成两个执行流

  • 子进程没有自己独立的代码和数据,因为目前没有程序新加载

让父子执行不同的代码
在这里插入图片描述
创建失败返回值小于0
在父进程里的代码中fork()返回值是子进程的pid
在子进程里的代码中fork()返回值是等于0的
在这里插入图片描述

  • 进程具有独立性
  • 数据默认是共享的,但父子如何一方,进行修改数据,OS就会把修改的数据在底层拷贝一份,让目标进程修改这个拷贝!(写时拷贝)

四、进程的状态

进程状态就是task_struct内的一个整数

  • 运行:进程在调度队列中,进程的状态都是running!
  • 阻塞:等待某种设备或者资源就绪,键盘、显示器、网卡、磁盘、摄像头、话筒……
  • 进程状态的变化,表现之一,就是要在不同的队列中进行流动。本质都是数据结构的增删查改!
  • 挂起:当操作系统的内存资源不足时,把进程的代码和数据换入到磁盘中,真正运行进程时再换入到内存里
1、Linux内核中进程的状态

在这里插入图片描述
R:运行状态
S:阻塞状态,可中断休眠,浅睡眠
D:深度睡眠,不可中断休眠
t:gdb时进程被debug暂停
T:用户Ctrl+z,进程暂停
X:结束状态
Z:僵尸状态,为了获取退出信息

2、孤儿进程
  • 父进程先结束,子进程的退出信息没有获取,此时子进程就称为孤儿进程

在这里插入图片描述

  • 父子进程关系中,如果父进程先退出,子进程要被1号进程领养,这个被领养的进程(子进程),叫做孤儿进程

1号进程是操作系统(init/systemd进程)
孤儿进程自动变成后台进程

五、进程的优先级

  • 优先级是进程得到CPU资源的先后顺序
  • 目标资源稀缺,导致要通过优先级确认谁先谁后的问题

在这里插入图片描述

1、ps -al 查看所有进程优先级的全部信息

在这里插入图片描述
UID:user id
PRI:进程的优先级,默认:80
NI:进程优先级的修正数据,nice值
进程真实的优先级 = PRI(默认) + NI
在这里插入图片描述
系统怎么知道访问文件的时候是用用于者,所属组还是other
Linux系统中,访问任何资源,都是进程访问,进程就代表用户

2、调整优先级

首先top,然后r,输入对应要调整的pid,最后输入调整NI的值
其他方法:nice,renice命令

在这里插入图片描述
优先级的极值:nice:[-20,19]
Linux进程的优先级范围[60,99]

3、竞争、独立、并行、并发

在这里插入图片描述

六、进程切换

在这里插入图片描述

  • 进程切换,最核心的,就是保存和恢复当前进程的硬件上下文的数据,即CPU内寄存器的内容
  • 当前进程要把自己的进程硬件上下文数据保存到task_struct里面,找到TSS任务状态段

七、Linux2.6内核进程O(1)调度队列

调度和切换共同构成了调度器
在这里插入图片描述

  • ⼀个CPU拥有⼀个runqueue
  • 如果有多个CPU就要考虑进程个数的负载均衡问题

queue[140]是调度队列:
1、其中0~99是实时优先级
2、而剩下的,100~139这 40 个优先级对应的进程优先级范围为[60,99],是一个哈希,在计算映射关系时只需要加40

bitmap是一个位图:
1、一个有 5 * 32 = 160个比特位,用来对应着调度队列
2、比特位的内容:1/0 表示是否为空

*active 指针指向一个调度队列
*expired 也指向一个调度队列
当active里的队列的进程执行一个时间片后,将进程放入到expired队列中,保证每个进程都能分到资源
当active队列没有进程后 swap(&active,&expired)

调度器快速挑选一个进程:1、挑队列 2、挑进程, 挑选进程的时间复杂度O(1)

实时操作系统:工业领域、制造类领域(来了个进程执行完)
实时操作系统:根据时间片来执行

八、环境变量

1、基本概念
  • 环境变量(environment variables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数
  • 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪⾥,但是照样可以链接成功,⽣成可执⾏程序,原因就是有相关环境变量帮助编译器进⾏查找。
  • 环境变量通常具有某些特殊⽤途,还有在系统当中通常具有全局特性
2、命令行参数

在这里插入图片描述
argv:是一个变长的char*类型的指针数组,指向一个一个字符串的地址
argc:代表数组当中元素的个数

然后打印里面的内容
在这里插入图片描述
在这里插入图片描述
把命令行参数以空格分隔给argv
在这里插入图片描述
main的命令行参数,是实现程序不同子功能的方法!
指令选项实现的实现原理

  • 进程拥有一张表,argv表,用来支持实现选项功能!
3、常见的环境变量
  • 要执行一个程序,必须先找到它

  • 系统中存在环境变量,来帮助系统找到目标二进制文件

  • 环境变量:PATH :系统中搜索指令的默认搜索路径

  • env(environment) 可以把系统中所以的环境变量挪列出来

  • 环境变量 = 名字 + 内容
    在这里插入图片描述

  • 根据一个环境变量的名字查看对应的内容
    在这里插入图片描述

  • 往PATH里加路径
    在这里插入图片描述

  • bash 形成一张表,环境变量表

  • bash内部有两张表,命令行参数表、环境变量表

  • 环境变量最开始是从系统的相关配置文件来的

配置文件存放地方:
在这里插入图片描述

  • HOME环境变量:保存当前用户家目录
    在这里插入图片描述
  • SHELL环境变量:当前Shell,它的值通常是/bin/bash,当前登录时用的那一个版本的shell
    在这里插入图片描述
  • USER:当前登录用户
    在这里插入图片描述
  • HOSTNAME:当前主机名
  • SSH_TTY:对应的终端设备
  • OLDPWD:上一次访问的目录

cd - :回到上一次访问的目录

4、获取环境变量的方法
  • env:查看所以环境变量
  • export:新导入环境变量
  • unset :取消环境变量

通过代码的方式获取环境变量:

方法1:main函数获取环境变量,获取环境变量是父进程的,环境变量可以被子进程继承
在这里插入图片描述

char *env[]:环境变量表

遍历环境变量表:
在这里插入图片描述

方法2:getenv系统调用
在这里插入图片描述
根据环境变量的名字获取内容
在这里插入图片描述

方法3:environ 全局变量
在这里插入图片描述
在这里插入图片描述

5、理解环境变量的特性
  • 环境变量具有全局特性
  • 本地变量,不会被子进程继承,只在bash内部使用
    在这里插入图片描述
  • set 命令显示环境变量和本地变量
    在这里插入图片描述
    bash 会记录两套变量:1.环境 2.本地

在这里插入图片描述

6、shell脚本

创建一个.sh的文件
文件里面的内容是命令行
批量化处理
在这里插入图片描述

九、程序地址空间

在这里插入图片描述

  • 程序地址空间不是内存
  • 程序地址空间叫做进程地址空间(虚拟地址空间),它是一个系统的概念,不是语言层的概念
1、虚拟地址空间

在这里插入图片描述

在这里插入图片描述
地址相同值不同,虚拟地址空间不是内存,不是物理内存

  • 一个进程,一个虚拟空间
  • 一个进程,一套页表
  • 页表是用来做虚拟地址和物理地址映射的
2、进程地址空间

在这里插入图片描述

进程里用于分配地址空间的数据结构
在这里插入图片描述
进程加载内容:
1、在虚拟地址空间中申请指定大小的空间
2、加载程序,申请物理空间
3、经过页表进行映射

3、为什么要有虚拟地址空间
  • 1、将地址从无序,变有序
  • 2、地址转换过程中,也可以对你的地址和操作进行合法判定,进而保护物理内存
  • 3、让进程管理和内存管理,进行一定程度的解耦合
4、如何解决堆区不连续的问题

在mm_struct中有一个vm_area_struct的链表把每一段堆区的起始地址和结束地址通过链表维护起来
在这里插入图片描述

  • 进程具有独立性:
  • 1、内核数据结构独立
  • 2、加载进入内存的代码和数据独立
;