回顾之前易忘记的知识
1.操作系统的发展历史中产生了多道技术: 多道技术:(多道指的是多道/个程序) 空间上的复用:内存中进入多个程序 PS:内存必须实现物理级别的隔离 时间上的复用:cpu要切换: 1. 一个程序占用cpu的时间过长 2. 一个程序遇到I/O阻塞 产生背景:针对单核,实现并发 2.网络传输五层协议:物理层 - 数据链路层(以太网协议--> head + data) - 网络层(IP -- 路由) - 传输层(TCP, UDP) - 应用层(HTTP) 3.变量的三个特征: id, type, value 4.可变类型是不可hash类型 hash 是什么? 不可变类型是可hash类型 5.集合的元素遵循三个原则:1:每个元素必须是不可变类型 2:没有重复的元素 3:无序 6.为什么py3中字符串是str py2中是bytes类型? 7.文件处理? 8.内置函数? 11. md5 一个文件 import hashlib md5_obj = hashlib.md5() import os filesize = os.path.getsize('filename') f = open('filename','rb') while filesize>0: if filesize > 1024: content = f.read(1024) filesize -= 1024 else: content = f.read(filesize) filesize -= filesize md5_obj.update(content) md5_obj.hexdigest() 12.socket 是什么? 它是网路传输过程中 应用层与传输层中间的一个接口, 它把复杂的TCP,UDP等协议封装在身后, 只留出我们看到的接口, 至于内部是怎么实现的网路连接等等不需要我们知道。 13. TCP 的三次握手 和四次挥手: 握手(我来了你准备好了吗--> 收到,我也准备好了,你来吧 --> 好的) 挥手(我要走了,你准备好了吗 --> 你先等一下我还有东西给你 --> 好了吗 --> 好了 ) 14.为何tcp是可靠传输,udp是不可靠传输? tcp在数据传输时,发送端先把数据发送到自己的缓存中,然后协议控制将缓存中的数据发往对端,对端返回一个ack=1,发送端则清理缓存中的数据,对端返回ack=0,则重新发送数据,所以tcp是可靠的 15.粘包: 1.发送数据时间间隔很短,数据了很小,会合到一起,产生粘包 2.接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包) 解决办法: 发送端先发送报头的长度 --> 发报头数据 --> 最后发送数据 16.操作系统的两大作用:一是为软件提供简单的接口来操作硬件。二是使多个软件对硬件的需求变得有序化 17.multiprocessing类实现开启子进程 (from multiprocessing import Process) p=Process() p.daemon = True # 守护进程,守护进程不可以再有子进程,并且主进程死守护进程就死,要写在p.start()之前 p.join() # 主进程等子进程执行完 之后再结束---> 等的时间就是执行时间最长的子进程执行的时间 p.terminate() # 强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,用该方法需要特别小心这种情况。如果p保存了一个锁那么也将不会被释放,进而导致死锁 p.is_alive() # 如果p仍然运行,返回True p.name # 查看进程的名称 p.pid -->查看进程的pid p.ppid -->查看进程的父进程pid 主进程不会等待子进程的结束,除非加了join方法 18.共享就存在竞争,----加锁-----队列 19.创建线程模块:from threading import Thread 多线程共享它们进程的资源,线程的创建比创建进程开销小 守护线程: 主线程的非守护线程执行完(主线程执行完毕)——>守护死 20.GIL 锁 与 Lock锁 21.进程池、线程池:from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor 进程池 默认个数是CPU个数,而线程池的默认个数是CPU个数的5倍 22.协程 优点:创建时消耗资源更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级 缺点:1.协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程 2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程 gevent 模块实现协程: from gevent import monkey;monkey.patch_all() #monkey;monkey.patch_all() 可以识别其他的I/O操作 import gevent import time,threading def eat(name): print('%s eat 1' %name) time.sleep(2) print('%s eat 2' %name) return 'eat' def play(name): print('%s play 1' %name) time.sleep(3) print('%s play 2' %name) return 'play' start=time.time() g1=gevent.spawn(eat,'egon') g2=gevent.spawn(play,'egon') # g1.join() # g2.join() gevent.joinall([g1,g2]) print('主',(time.time()-start)) print(g1.value) print(g2.value) # 结果: egon eat 1 egon play 1 egon eat 2 egon play 2 主 3.0018091201782227 eat play 23.select,poll,epoll实现IO多路复用机制 三个模块的区别: select模块自动监听多个套接字 (谁好了就返回谁) 但是监听的套接字(socket)个数不是无限多的 poll的实现机制和select时非常相似的 epoll模型可以解决套接字个数非常多的情况(因为它的内部检测哪个套接字好了的机制和select不同 (select是遍历每个套接字,看有没有好了的, 而epoll是 如果哪个套接字好了,就自动跑出来)), 但是windows不支持epoll模型 24.数据库的curd基本语句 25.InnoDB 支持事务,支持行级别锁定、 Memory 不支持事务,支持表级别锁定, MyISAM 不支持事务,支持表级别锁定 26.from multiprocessing import Process,JoinableQueue,Queue import time,random,os def consumer(q): while True: res=q.get() if res is None:break #收到结束信号则结束 time.sleep(random.randint(1,3)) print('\033[45m%s 吃 %s\033[0m' %(os.getpid(),res)) q.task_done() # 向q.join()发送一次信号,证明一个数据已经被取走了 def producer(name,q): for i in range(2): time.sleep(random.randint(1,3)) res='%s%s' %(name,i) q.put(res) print('\033[44m%s 生产了 %s\033[0m' %(os.getpid(),res)) # q.join() #q.join除了可以放在主进程里面,也可以放在这里 if __name__ == '__main__': q=JoinableQueue() #生产者们:即厨师们 p1=Process(target=producer,args=('包子',q)) p2=Process(target=producer,args=('骨头',q)) p3=Process(target=producer,args=('泔水',q)) #消费者们:即吃货们 c1=Process(target=consumer,args=(q,)) c2=Process(target=consumer,args=(q,)) c1.daemon=True #设置成守护进程 c2.daemon=True #开始 p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() #必须保证生产者全部生产完毕,才应该发送结束信号 p2.join() p3.join() q.join() #生产者和消费者的进程都完成了 print('主') #为什么设置消费者为守护进程,因为执行到最后,生产者进程执行完了,主进程也完成了,但是由于消费者 #进程是死循环,并没有结束,设置成守护进程后,主进程结束了,c1和c2也就可以结束了 27. 现有两个元组(('a'),('b')),(('c'),('d')), 请使用python中匿名函数生成列表[{'a':'c'},{'b':'d'}] 28. assert 断言是什么?它的使用场景? 29. logging模块的使用 import logging def my_logger(filename,file=True,stream = True): logger = logging.getLogger() formatter = logging.Formatter(fmt='%(name)s %(asctime)s [%(lineno)d] -- %(message)s', datefmt='%d/%m/%y %H:%M:%S') logger.setLevel(logging.DEBUG) if file: file_handler = logging.FileHandler(filename,encoding='utf-8') file_handler.setFormatter(formatter) # 文件流 文件操作符 logger.addHandler(file_handler) if stream: stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) #屏幕流 屏幕操作符 logger.addHandler(stream_handler) return logger logger = my_logger('logging',file=False) logger.warning("出错了")