python网络编程目录
异步编程
1.进程间通信
进程间通信(IPC,Inter-Process Communication)是指在不同进程之间传播或交换信息
IPC的方式通常有管道(包括 无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等、
进程
进程是具有一定功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信
进程间通信的几种类型
管道,通常是指无名管道,是Unix系统IPC最古老的形式
- 半双工(即数据只能在一个方向上流动),具有固定的读端和写端。
- 只能用于具有亲缘关系的进程之间的通信(父子进程或者兄弟进程之间)。
- 可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write等函数,但它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中
- 通过系统函数int pipe(int __pipedes[2])进行创建
FIFO,命名管道,一种特殊文件类型 - FIFO可以在无关的进程之间交换数据,与无名管道不同
- FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中,命名管道,FIFO是一种特殊文件类型
命名管道有mkfifo函数创建,打开用open。
FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在于它们创建与打开的方式不同,这些工作完成之后,它们具有相同的语义。
消息队列
消息队列是消息的链接表,存放于内核中。一个消息队列又一个标识符(即队列ID)来标识 - 消息队列是面向记录的,其中消息具有特定的格式以及特定的优先级
- 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除
- 消息队列可以实现消息的随机查询,消息不一定要一先进先出的次序读取,也可以按照类型读取
信号量
信号量(semaphore)与已经介绍过的IPC结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据
- 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
- 信号量基于操作系统PV操作,程序对信号量的操作都是原子操作。
- 每次对信号量的PV操作不仅限于对信号量的加1或减1,而且可以加减任意正整数。
- 支持信号量组
共享内存
共享内存(Shared Memory)指的是两个或多个进程共享一个给定的存储区 - 共享内存是最快的一种IPC,因为进程是直接堆内存进行存取的。
- 因为多个进程可以同时操作,所以需要进行同步。
- 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
PV操作
这个是狄克思特拉用荷兰文定义的,因为在荷兰文中 ,通过叫passeren,释放叫做VRIJGEVEN,PV 操作因为得名
原子操作
如果这个操作所处的层(layer)的更高层不能发现其内部实现与结构,那么这个操作就是一个原子(atomic)操作
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中一部分。
进程的基本特征
动态性
并发性
独立性
异步型
进程的状态转换
进程控制块(Processing Control Block)
也称为进程描述块(Process Descriptor)操作系统核心中 的一种数据结构,主要标识进程状态。在创建进程时首先建立PCB,它伴随进程运行的整个过程,知道进程撤销而报销。系统可以利用 PCB来控制和管理进程,所以说PCB(进程控制块)是系统感知进程存在的唯一标志。
- 进程标识符(Process ID)、进程名、用户标识符(user ID)进程组关系。每个进程都必须有一个标识符,通常是一个整数。
- 当前状态、优先级、程序的磁盘地址、代码开始地址、进程队列指针、通信信息
- 虚拟地址空间的状况、打开文件列表
- 寄存器值(通用寄存器。程序计数器PC、程序状态字PSW、栈指针)、指向该进程页表的指针
unix系统 中的几个进程 控制操作
fork():通过复制调用进程来建立新的进程,是最基本的进程建立过程(创建进程,昂贵,消耗资源)
exec():包括一系列系统调用 ,他们是通过用一段新的程序代买覆盖原来的地址空间,实现进程执行代码的转换。
wait():提供初级进程同步操作,能使一个进程等待另外一个进程结束。
exit():用来终止一个进程的执行
IPC:父进程向子进程传递数据容易,子传递给父进程很难
线程(lightweight process)
线程:进程的一个可调度的实体CPU调度的基本单位 ,不拥有系统资源消耗资源少,多线程可以相互交互
线程之间共享:
- 进程指令
- 大多数数据
- 打开的文件(描述符)
- 信号处理函数和信号处理
- 用户ID和组ID
线程的独立信息: - 线程ID
- 寄存器集合,(程序计数器和栈指针)
- 栈(用于存放局部变量和返回地址)
- erron
- 信号掩码
- 优先级
现成的额创建:
系统底层的pthread_create创建线程
在POXIS规范的系统中称pthread
线程VS进程
-
地址空间
线程是进程的执行单元 -
资源使用
进程是资源分配的单位 -
CPU调度
线程是CPU调度的基本单位 -
并发
-
是否独立
线程不能独立运行
IO模型
I/O操作的两个阶段
1.内核等待数据
2.从内核向进程复制数据
- 阻塞式
- 非阻塞式
- I/O复用
当客户处理多个描述符(一般是交互式输入或网络套接字)必须适用I/O复用当一个客户处理多个套接字时,这种情况很少见,但也能出现
当一个TCP服务器既要处理监听套接字,又要处理已连接套接字,一般就要适用I/O复用
如果一个服务器既要适用TCP又要适用UDP一般就使用I/O复用
如果一个服务器要处理多个服务或者多个协议,一般就要使用I/O复用
- 信号驱动式
- 异步I/O
并发VS并行
异步vs同步
2.多线程与多进程的用法
计算密集型vs I/O密集型
GIL
Global Interpreter Lock
什么时候使用多线程?
I/O密集型:文件读写,网络传输
什么时候使用多进程?
CPU密集型的计算问题
多线程
多线程的注意问题:
锁 的
linux底层:
互斥锁mutex:mutual exclusion
保护共享变量:解决多个线程更改一个共享变量的问题,提供互斥机制。
互斥锁是类型 为pthread_mutes_t的变量
线程启动程序
#!/usr/bin/env python3
# -*-coding :utf-8 -*-
__author__ = 'gyz'
from threading import Thread
import time
def countdown(n):
while n > 0 :
print('倒数开始 :',n)
n -= 1
time.sleep(1)
def main():
# countdown()
t = Thread(target=countdown,args=(5,))
t.start()
if __name__ == '__main__':
main()