目录
1 进程 & 线程
1.1 进程(process)
1.1.1 定义
进程:是程序的一次执行过程
资源分配的独立单位
4个程序创建4个进程(微信,TIM,浏览器,spyder),并发运行:
1.1.2 组成(3个)
组成:控制块PCB、程序段、数据段
PCB:进程控制块,Process Control Block
描述进程的,基本信息,运行状态
创建、撤销:是对PCB的操作
1.1.3 状态(5种)
(1) 创建 :进程正在被创建
(2) 就绪 :进程获得了处理机以外的一切所需资源,一旦得到了处理机就可以运行
(3) 运行 :进程正在处理机上运行
(4) 阻塞(等待) :进程正在等待某一时间而暂停
(5) 结束 :正在退出,结束运行
阻塞不能直接回到运行,需要经历就绪
1.1.4 多进程
(1)一个进程可以包括多个线程
(2)并行运行(同一时刻)(同时执行多任务,占用多个cpu资源)
进程间交流需要通过一个中间代理
创建进程需要对父进程进行一次克隆
改变父进程,不影响子进程
多进程
最大的优点:稳定性高(子进程崩,不影响主进程和其他子进程)
缺点:进程切换开销大(有独立的代码和数据空间),能运行的进程数有限
进程通信(6种,是手段)
通信目的:数据交换
进程之间不能直接通信,需要借助中间代理(IPC)
通信方式包括6种:
(1) 管道
半双工,父子/兄弟进程
- 命名管道:FIFO
非亲缘通信
(2) 消息队列
格式化消息单位,数据交换
(3) 信号量
计数器,访问共享资源
(4) 共享内存
共享存储区,不用复制数据,最快
需要信号量同步
(5) 套接字
不同机器间
(6) 信号
进程同步(是目的)
多进程, 有一定的先后执行关系
多进程,只有一个能进入临界区(访问临界资源的代码)
信号量=0,临界区加锁
信号量=1,临界区解锁
1.1.6 python实现
创建进程:
from multiprocessing import Process
## 打印列表信息的函数
def print_info(*args, **kargs)
print(args,kwargs)
def main():
## 信息列表
li = [{"name":"python 基础","progress":"10%"},
{"name": "python 面向对象", "progress": "20%"},
{"name": "python 爬虫", "progress": "30%"},
{"name": "python pyqt5", "progress": "40%"},
{"name": "python 数据结构", "progress": "50%"},]
## 创建进程
for i in range(5):
p = Process(target=print_info, args=(i,), kargs=(li[i])
## 启动进程
p.start()
if __name__== "__main__”:
main()
输出:
(0,) {'name': 'python 基础', 'progress': '10%'}
(1,) {'name': 'python 面向对象', 'progress': '20%'}
(2,) {'name': 'python 爬虫', 'progress': '30%'}
(3,) {'name': 'python pyqt5', 'progress': '40%'}
(4,) {'name': 'python 数据结构', 'progress': '50%'}
1.2 线程(threading)
1.2.1 定义
线程:是进程的子任务
又称:轻量级进程,轻权进程
资源调度的独立单位——CPU调度
计算机最小单位
1个进程包含多进程(http请求,事件响应,渲染):
1.2.2 四个状态
(1) 新建 :线程对象被创建后,就进入了新建状态
(2) 就绪(可执行) :线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。如,thread.start()。处于该状态,随时可能被CPU调度执行
(3) 运行 :获取CPU权限进行执行
(4) 阻塞(等待) :线程因为某种原因放弃CPU使用权,暂时停止运行。
线程只能从就绪状态进入到运行状态
1.2.3 多线程
(1)1进程下的多线程,共享进程的所有资源(堆,方法)
(2)只有1个cpu被使用,一时刻,只运行1个线程
(3)并发运行(同一时间段)(GIL锁)
1个cpu在多个线程(任务),来回切换(调度)
切换速度足够快,多线程并发运行
同一进程的线程可以直接交流
可以直接创建新线程
改变主线程,会影响其他线程
-
多线程优点:
(1)适当提高,程序执行效率
(2)适当提高,资源利用率(cpu,内存)
(3)线程切换开销小(每个线程有独立的运行栈和程序计数器PC) -
多线程缺点:
(1)开线程,占内存
(2)线程越多,调度开销越大
(3)程序设计复杂(通信,数据共享)
(4)任何线程挂掉,可能造成进程崩溃(所有线程共享进程资源)——致命 -
在ios程序开发中的应用:
主线程:ios程序运行,默认开启1条
主线程作用:显示/刷新UI界面;处理UI事件(点击、滚动、拖拽)
线程通信(4种)
通信目的:线程同步
通信特点:线程间可以直接通信
通信方式包括4种:
(1)锁机制
(2)信号量机制
(3)信号机制
(4)屏障
线程同步
1.2.3 python实现
创建线程:
from threading import Thread
## 打印列表信息的函数
def print_info(*args, **kargs):
print(args,kwargs)
def main():
## 信息列表
li = [{"name":"python 基础","progress":"10%"},
{"name": "python 面向对象", "progress": "20%"},
{"name": "python 爬虫", "progress": "30%"},
{"name": "python pyqt5", "progress": "40%"},
{"name": "python 数据结构", "progress": "50%"},]
## 创建线程
for i in range(5):
t = Thread(target=print_info, args=(i,), kargs=(li[i])
## 启动线程
t.start()
if __name__== "__main__”:
main()
输出:
(0,) {'name': 'python 基础', 'progress': '10%'}
(1,) {'name': 'python 面向对象', 'progress': '20%'}
(2,) {'name': 'python 爬虫', 'progress': '30%'}
(3,) {'name': 'python pyqt5', 'progress': '40%'}
(4,) {'name': 'python 数据结构', 'progress': '50%'}
1.3 协程
又称:微线程
进程和线程的共同问题:内核态和用户态的切换问题
用户自己控制切换时机,不需要陷入内核态
1.4 进程和程序对比
(1)程序是代码,静态的;进程是程序的运行过程,是动态的
(2)程序=代码+数据;进程=代码+数据+堆栈+PCB
(3)程序是永久的;进程是暂时的
(4)程序没有并发性;进程有
(5)1程序可对应多进程;1进程可执行多程序
1.5 进程和线程对比
进程VS线程:
(1)根本区别
进程——资源分配
线程——资源调度与执行
(2)影响关系
进程包括线程(轻量级进程)
进程比线程(共享进程资源)稳定
改变父进程,不影响子进程
改变主线程,可能影响其他线程
(3)资源开销
进程——创建占用计算资源大,切换开销大
线程——创建占用计算资源小,切换开销小
(4)内存分配
进程间的资源相互独立
线程共享进程的资源
(5)执行过程
进程并行运行
线程并发运行
(6)通信方式
进程间需要中间代理
同一进程的线程间可以直接进行
(7)编程调试
进程简单
线程复杂
(8)分布式
进程适用于:多核多机
线程适用于:多核
1.6 GIL锁(线程相关)
GIL引起的问题:线程无法并行(同一时间,只有1个线程能被解释器解释,多核资源没有被充分利用)
多线程==单核cpu下的多进程
-
怎么解决GIL锁问题?
(1)将cpython换成python
(2)用多进程完成多线程任务
(3)用C语言实现多线程 -
何时释放GIL锁?
(1)cpu闲置时
如,I/O操作,会有时间空闲
(2)ticks计数达到100时
线程间开始竞争
如,延长/缩短ticks的数值,控制线程使用cpu的时间 -
互斥锁和GIL锁的关系?
互斥锁:多线程,有序修改共享数据,防止修改混乱
GIL锁:保证同一时刻只有1个线程用到cpu
2 select & poll & epoll
所有I/O:轮询方法(实现层面不同)
I/O多路复用
select的3个缺点:
(1)连接数受限
(2)查找、配对,速度慢
(3)数据由内核态拷贝到用户态
poll改善(1)
epoll改善(1)(2)(3)
3 (进程)调度算法
-
批处理系统
(1)先来先服务(FCFS)
first come first serve
(2)短作业优先(SJF)
shortest job first
(3)最高优先权调度
priority scheduling -
交互式系统
(4)时间片轮转(RR)
round robin
按照FCFS排成队列,每个时间片,CPU给队首,没来得及处理的送去队尾
(5)优先级调度
每个进程,分配一个优先级,随时间增加,等待进程优先级增加
(6)多级反馈队列调度
multilevel feedback queue scheduling
连续执行多个时间片,每个队列时间片大小不同,优先权不同 -
实时系统
(7)最早截至时间优先(EDF)
(8)最低松弛度优先(LLF)
实时os:保证在一定时间限制内,完成特定功能
硬实时(规定时间),软实时(按优先级尽快)
4 死锁
4.1原因
(1)资源竞争
(2)进程推进顺序不当
4.2 必要条件
(1)互斥
(2)请求和保持
(3)不剥夺
(4)环路
4.3 处理
(1)预防:摒弃条件(2)-(4)
(2)检测:资源分配图
(3)避免:银行家算法
(4)解除:剥夺资源;撤销进程
5 程序运行过程
build过程的4个步骤:预处理,编译,汇编,链接
.c 是 .cpp,源文件
.i 是 .inter, 中间文件文件(intermediate )
.s 是 .ass, 汇编代码文件(assembly)
.o 是 .obj, 目标文件(object)
.e 是 .exe,可执行文件(execute)
源代码文件:.c, .C,.cc, .cxx,.cp,.cpp, .CPP,.c++
gcc的四个阶段
5.1 预处理(处理“#”)
- 输入:.cpp
- 作用:
(1)展开宏;
(2)在程序中插入include包含的文件
(1)定义:“#define”——展开宏定义
(2)条件:“#if”——处理
(3)包含:“#include”——文件插入指定位置(递归进行)
(4)注释:删除所有注释
(5)标识:行号,文件名
(6)保留#pragma:编译器指令
- 输出:.i
5.2 编译(检查)
- 输入:.i
- 作用:
(1)检查代码的规范、语法错误;
(2)把.i文件编译成可读汇编代码 - 输出:.s
5.3 汇编(转成机器指令)
- 输入:.s
- 作用:
(1)把.s文件汇编成cpu上的目标代码 - 输出:.o
5.4 链接(链接库)
- 输入:.o
- 作用:
(1)把.o文件与相关代码链接,生成可执行二进制代码 - 输出:.e
处理模块间的引用,以便正确拼接
步骤: (1)地址和空间分配 (2)符号决议 (3)重定位
6 静态&动态链接
6.1 静态链接
(1)载入代码,就确定代码的逻辑地址
(2)库在exe文件形成时,装入和链接
6.2 动态链接
(1)调用到时,才计算代码的逻辑地址
(2)库在程序运行时,装入和链接
6.3 静态 VS 动态
静态运行性能好
动态初始化时间短
7 虚拟内存
虚拟存储器:请求调入、置换功能,从逻辑上扩充内存容量,存储系统
8 分页&分段
8.1 分页
程序地址空间,被分为:多个大小相等的区域——页
内存空间,被分为:多个物理块——块
页大小=块大小
离散分配:程序的任一页,放在内存的任一块
8.2 分段
程序地址空间,被分为:多个大小不等的区域——段
每段:一组相对完整的逻辑信息
离散分配:以段为单位,段与段不相邻
9 页面置换算法
9.1 定义
地址映射过程,所要访问的页面不在内存中,产生缺页中断。
若os内存中没有空闲页面,必须淘汰一个,为将调入的让位。
选择淘汰哪一页的算法——页面置换算法
9.2 分类
全局置换:在,整个内存中,置换
局部置换:在,当前进程中,置换
9.3 算法
全局置换算法:
(1)工作集
(2)缺页率置换
局部置换算法:
(1)最佳(OPT):不可能实现
(2)先进先出(FIFO)
(3)最近最久未使用(LRU)
(4)Clock
10 边沿&水平触发
边沿:状态变化,发生一io事件
条件:满足条件,发生一io事件
11 文件系统
Windows: FCB表+FAT+位图
Unix:inode+混合索引+成组链接
12 主机字节序&网络字节序
12.1 主机(CPU)字节序
与os无关,由CPU指令集架构决定
分类方式
大端:高序在低位,低序在高位
小端:高序在高位,低序在低位
高序在高位:高序字节存储在高位地址
存储方式
32位整数:0x12345678
地址 | 0x00(高) | 0x01 | 0x02 | 0x03(低) |
---|---|---|---|---|
大端 | 12(低序) | 34 | 56 | 78(高序) |
小端 | 78 | 56 | 34 | 12 |
判断CPU的大小端
代码如下:
#include <iostream>
using namespace std;
int main()
{
int i = 0x12345678;
if (*((char*)&i) == 0x12) # 大端:0x12
cout << "大端" << endl;
else # 小端:0x78
cout << "小端" << endl;
return 0;
}
架构处理器的字节序
- 大端:Motorola 6800、Motorola 68000、PowerPC 970、System/370、SPARC(除 V9 外)
- 小端:x86(Intel、AMD)、MOS Technology 6502、Z80、VAX、PDP-11
- 可配置:ARM(默认小端序)、PowerPC(除 PowerPC 970 外)、DEC Alpha、SPARC
V9、MIPS、PA-RISC 及,IA64
12.2 网络字节序(大端)
与os,CPU类型无关
TCP/IP 中规定好的数据表示格式
保证数据,在不同主机间传输,能够被正确解释
13 linux常用指令
13.1 文件查看&查找&统计
(1)查看:
ls -la # 列出当前工作目录下,所有文件/文件夹名(包含隐藏文件)
ls -lh # 列出文件,可读性较高
pwd # 打印当前工作目录
ls xxx | grep y # 输出xxx目录下,包含y字母的文件名
(2)查找:
find xxx -name # 按名称搜
find xxx -type # 按类型搜
(3)统计文件数量:
wc -l xxx # 行数,统计文档总数
wc -w xxx # 单词数
wc -c xxx # 字节数
ls xxx | wc -l # 统计xxx目录下,文档总数
13.2 目录操作
(4)切换目录:
cd xxx # 切换当前工作目录
(5)创建目录:
mkdir xxx # 创建目录
mkdir -p xxx # 创建多层目录
13.3 文件操作
(6)创建文件:
touch xxx # 创建文件
(7)复制:
cp xxx1 xxx2 # 将路径1下的文件复制到路径2
cp -r xxx1 xxx2 # 复制文件夹(嵌套关系用-r)
(8)移动:
mv xxx1 xxx2 # 将路径1下的文件移动到路径2
(9)重命名:
mv old new
(10)删除:
rm xxx # 删除路径下的文档
rm -f xxx # 强制删除,不用确认
rm -r xxx # 删除文件夹(嵌套关系用-r)
rm -rf xxx
(11)打开/编辑文件:
vim xxx # 打开文件,(退出用shift+:+q)
cat xxx # 打开文件,自动退出
(12)查看文件内容的前n行,后n行
head -n xxx # 看文档前n行
tail -n xxx # 看文档后n行
less xxx # 以较少的内容输出
13.4 空间&进程&服务操作
(13)查看空间:
df -h # 磁盘空间,可读性高
free -m # 内存空间,以M为单位显示
(14)查看,杀死进程:
ps -ef # 查看多进程信息
ps -ef | grep xxx # 查看xxx进程的信息
top # 查看多进程所占资源
kill xxx # 杀死PID为xxx的进程
killall xxx # 强制杀死PID为xxx的进程
top指令:
(15)启动,停止,重启服务:
service xxx start # 启动服务
service xxx stop # 停止服务
service xxx restart # 重启服务
13.5 命令行操作
(16)将命令行输出保存到文件(输出重定向):
ls -la > ls.txt # 覆盖原先内容
ls -la >> ls.txt # 在原先内容,后面追加
(17)清除终端信息:
clear # 快捷键Ctrl+L
13.6 显示系统信息
(18)显示日历,日期:
cal -3 # 显示本月日历
date “ +%Y-%m-%d %H%M%S” # 显示年月日,时分秒
(19)查看主机名,用户信息,登录的用户名:
hostname # 查看主机名
id # 查看用户信息
whoami # 查看登录的用户名
(20)获取操作系统信息
uname # 获取os类型
uname -a # 获取os全部信息
13.7 重启&关机
(21)重启,关机:
reboot # 重启
reboot -w # 模糊重启
shutdown -h now # like关机
shutdown - h 15:30 # 定时关机
(shutdown -c是取消关机)
(22)计算机持续在线时间
uptime
13.8 命令手册
(23)全部命令手册
man xxx # 查询xxx命令的用法
14 linux目录结构
- /usr:Unix Software Resource,Unix操作系统软件资源所放置的目录,而不是用户的数据。 FHS建议所有软件开发者,应将数据合理的分别放置到这个目录下的次目录,而不要自行建立该软件自己独立的目录。
- /tmp:让一般使用者或是正在执行的程序暂时放置档案的地方。任何人都能够存取,需要定期清理。重要资料不可放置在此目录,因为FHS甚至建议在开机时,应该要将/tmp下的资料都删除。
- /etc:系统主要的设定档几乎都放置在这个目录内,例如人员的帐号密码档、各种服务的启始档等等。 一般来说,这个目录下的各档案属性是可以让一般使用者查阅的,但是只有root有权力修改。 FHS建议不要放置可执行档(binary)在这个目录中。
比较重要的档案有:/etc/inittab, /etc/init.d/, /etc/modprobe.conf, /etc/X11/, /etc/fstab, /etc/sysconfig/等等。
参考
https://github.com/taizilongxu/interview_python#28-python2%E5%92%8C3%E7%9A%84%E5%8C%BA%E5%88%AB
https://zhuanlan.zhihu.com/p/101036955
https://www.zhihu.com/question/318883649/answer/644070872
http://www.360doc.com/content/15/1030/22/22195712_509552843.shtml
https://blog.csdn.net/chris__x/article/details/107190660
https://github.com/CyC2018/CS-Notes/blob/master/notes/%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%20-%20%E8%BF%9B%E7%A8%8B%E7%AE%A1%E7%90%86.md
https://www.cnblogs.com/silence-hust/p/4319415.html
https://blog.csdn.net/qq_38410730/article/details/80951443