正邦做网站吗谷歌seo建站
- 作者: 五速梦信息网
- 时间: 2026年04月20日 03:43
当前位置: 首页 > news >正文
正邦做网站吗,谷歌seo建站,wordpress sqllite,江阴市建设局网站文章目录 计算机内存分配进程与子进程流IO模型非阻塞IOIO多路复用网络IO模型简单的socket并发的socket 计算机内存分配
一个32位#xff0c;4G内存的计算机#xff0c;内存使用分为两部分#xff1a;
操作系统内核空间#xff1b;应用程序的用户空间使用的操作系统不同4G内存的计算机内存使用分为两部分
操作系统内核空间应用程序的用户空间使用的操作系统不同分配方式不同
进程与子进程 进程是操作系统中资源管理的最小单位它是将静态程序加载到内存中的一次动态的执行包括进程创建、进程调度、进程销毁 每个进程有自己独有的内存在用户空间内进程的私有内存是相互独立的且进程间无法直接通信 不同进程间通信可以采用队列、管道、信号、共享内存内核空间内等方式 每个进程中可以创建一个或者多个线程多个线程共享当前进程的部分内存资源如代码、全局变量等 进程的内存分布 比如上图中的shell脚本运行时shell是父进程python3开启子进程父进程会等待子进程退出当关闭shell进程父进程时python3子进程由init进程接管。 父进程中当以fork()系统调用创建子进程时子进程执行exit()系统调用退出后内核中仍然存有子进程的信息如pid, exit code, run time等这些信息要等父进程通过wait/waitpid来回收若一直未回收则退出的子进程成为僵尸进程一直占用系统资源。 僵持进程无法通过kill关闭随着数量增多系统资源耗尽导致系统瘫痪。
流
可以进行IOinput输入、output输出操作的内核对象如文件、管道、socket…流的入口是fd (file descriptor)
IO模型 阻塞IO 一直等待不占用资源无法同时处理多个任务 用户进程发起读的系统调用当内核中socket fd未就绪时一直阻塞等待 socket fd 就绪时将内核中的socket数据拷贝到用户空间拷贝期间阻塞等待 accept()阻塞 非阻塞IO 忙轮询占用CPU 应用程序不断轮询内核对应的socket fd是否就绪未就绪则返回非阻塞 若已就绪则拷贝内核中socket的数据到用户空间阻塞。 accept()不阻塞 IO多路复用多个IO复用一个进程/线程既可以阻塞等待不占用资源又可以同时并发处理多个任务 linux 支持select poll epoll应用程序通过系统调用让内核同时监控多个socket fd一旦有网络事件发生内核就遍历找到对应的socket将其标记为可读然后将所有的socket fd返回给应用程序应用程序遍历所有的fd找到就绪的fd通过系统调用复制对应socket的数据到用户空间 异步IO; 应用程序发起异步read操作后立即返回 内核中的fd就绪复制数据完成触发信号通知应用程序 全程无阻塞 信号驱动IO 首先注册信号处理函数 检查内核socket fd 是否就绪未就绪直接返回 已就绪则内核发送信号给应用程序触发信号处理函数 信号处理函数发起系统调用从内核空间拷贝socket数据到用户空间阻塞 非阻塞IO
忙轮询占用CPU性能不如阻塞IO代码流程不停地 遍历所有的fd查看是否就绪 IO多路复用
多个IO复用一个进程/线程既可以阻塞等待不占用资源又可以同时并发处理多个任务 select 最大连接数默认1024两次拷贝先将所有的fd 从用户空间拷贝到内核空间由内核监控是否有fd就绪可读或可写也就是有网络事件发生一旦有fd就绪则遍历所有的fd集合找到对应的fd并将其 标记为就绪态可读、可写然后将所有的fdfd集合从内核空间拷贝到用户空间用户进程内遍历所有的fd找出就绪的从进行读写两次遍历并发量大时性能指数式下降代码流程 poll与select 没有本质的区别只是连接数比select多 select 使用固定长度的 BitMap表示文件描述符集合而poll 使用动态数组以链表形式来组织突破了 select 的文件描述符个数限制还会受到系统文件描述符限制。select/poll 都是使用线性结构存储进程的 socket 集合都需要遍历文件描述符集合来找到可读或可写的 socket时间复杂度为 O(n)而且也需要在用户态与内核态之间拷贝文件描述符集合。 epoll高性能的IO多路复用仅linux支持 连接数更大上限为进程的最大连接数查看最大连接数cat /proc/sys/fs/file-max内核中采用红黑树结构可高效地增删查O(logn)仅返回就绪的fd将就绪的fd拷贝给用户进程避免无用的遍历适合并发量大的场景可以解决C10K问题单台服务器并发1w 操作流程使用epoll_create 创建内核epoll对象epoll_ctl将要监控的socket加入红黑树内核检测到有网络事件发生则将对应的socket 连接放入一个就绪链表中并复制给用户空间epoll_wait返回; epoll支持水平触发和边缘触发边缘触发效率更高select/poll仅仅支持水平触发即内核socket缓冲区有数据就绪在数据没有被进程读取完之前会多次通知进程来读取而边缘触发则仅仅通知一次需要进程一次性读取所有的数据。例如当快递放入快递站点时管理员可能给你打多个电话催促你取快递这种通知多次的方式就是水平触发而当快递放入快递柜时就只给你发送一次短信仅仅通知一次这种仅仅通知一次的方式就是边缘触发。IO多路复用中有socket 就绪并不一定可读、可写此时为避免进程阻塞需要结合非阻塞IO一起使用。 网络IO模型
基于socket网络通信 客户端与服务端建立连接的过程 客户端的socket对象调用connect((ip, port))服务器的网卡接收请求并转发给OS 实现TCP三次握手同时在操作系统内核中维护两个队列TCP半连接队列 TCP全连接队列半连接队列表示未完成三次握手全连接队列表示完成三次握手已完成socket连接内核从TCP全连接队列取出当前socket连接存储到内核文件列表中同时将其fd返回用户空间存入进程数组应用程序中就可以拿着这个已连接的socket进行读写读/写时 就对应阻塞IO、非阻塞IO、IO多路复用、异步IO、信号驱动的IO的情况
下面以python3语言为例演示socket的使用。
简单的socket
同时只能处理一个客户端的请求。
server:
import socket
import time
import sys
import signal # 注册信号的处理函数def handler(signum: int, frame):接收到SIGINT信号时打印一句话并退出进程print(received signal:, signum)sys.exit(0)# 注册信号的处理函数
signal.signal(signal.SIGINT, handler) # 使用 Ctrl C 发送SIGINT信号# 网络层使用Ipv4
传输层使用TCP
sock_server socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 默认为阻塞的socket# 绑定ip sock_server.bind((localhost, 8000))
最多监听1000个连接
sock_server.listen(1000) # 监听的socketwhile True:# TCP三次握手完成接收socket连接conn, addr sock_server.accept() # accept阻塞 等待 socket连接就绪# 处理当前的socket连接conn是已连接的socketprint(conn:, conn, addr)# 读 IO操作data conn.recv(1024) # 阻塞等待 内核中socket就绪并拷贝数据到用户空间 print(received data:, data.decode())# 写 IO操作拷贝到内核空间写入socket缓冲区conn.send(bhello, i am server. I have got your data.)# 在当前socket连接 的请求处理完之前服务端不会接收下一个客户端的socket连接time.sleep(20)client: import socket import time# 创建客户端 sock_client socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 建立连接 sock_client.connect((localhost, 8000))# 发送数据 sock_client.send(bhello, i am jack) print(发送数据完成.)# 接收数据 data sock_client.recv(1024) # 接收 1024 bytes # 阻塞 内核fd未就绪-就绪 内核socket数据复制到用户空间 print(received data:, data.decode())并发的socket 同时可以处理多个客户端的请求。 阻塞多进程 随着请求数量的增多子进程越来越多fork创建子进程复制父进程所有的资源占用的系统资源越来越多并发量大时会影响系统的性能甚至导致系统崩溃多进程上下文的切换包括用户空间、内核空间消耗系统性能所以并发量特别大时多进程不是理想的方案。
server.py
import socket
import os
import time
import sys
import signal # 注册信号的处理函数
import multiprocessingdef handler(signum: int, frame):接收到SIGINT信号时打印一句话并退出进程print(received signal:, signum)sys.exit(0)# 注册信号的处理函数
signal.signal(signal.SIGINT, handler) # 使用 Ctrl C 发送SIGINT信号# 处理请求
def handle_request(conn, addr):print(subprocess:, os.getpid())print(conn:, conn, addr)flag Falsewhile not flag:# 接收数据data conn.recv(1024) # recv from kernelprint(received data:, data.decode())# 发送数据conn.send(bI am server. I have got your data.)# 检测客户端的断开data conn.recv(1024)print(客户端断开, data.decode())if not data:conn.close()print(客户端已断开.)flag Trueprint(f{os.getpid()}子进程退出.)if name main:# 网络层使用Ipv4# 传输层使用TCPsock_server socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 默认为阻塞的socket# 绑定ipsock_server.bind((localhost, 8000))# 最多监听1000个连接sock_server.listen(1000) # 监听的socketwhile True:# TCP三次握手完成接收socket连接conn, addr sock_server.accept() # accept阻塞 等待 socket连接就绪# 父进程 阻塞等待连接print(创建子进程.)# 子进程处理 请求sub_process multiprocessing.Process(targethandle_request, args(conn, addr))sub_process.daemon Truesub_process.start()# client.py
import socket
import time# 创建客户端
sock_client socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 建立连接
sock_client.connect((localhost, 8000))# 发送数据
sock_client.send(bhello, i am jack)
print(发送数据完成.)# 接收数据
data sock_client.recv(1024) # 接收 1024 bytes
print(received data:, data.decode())sock_client.close() # 客户端断开连接会发送空数据到服务端阻塞多线程 线程是轻量级进程同一个进程的多个线程可以共享当前进程的部分资源代码、全局变量等避免了过多的资源消耗多线程的上下文切换虽比多进程轻量但大量的线程来回切换也会给系统造成不小的开销多线程需要考虑线程安全问题另外每个线程也有自己的栈空间也消耗内存大量的线程必然会消耗大量的栈空间所以对于特别大的并发量时多线程也不是理想的方案。
在这里插入代码片IO多路复用
- 上一篇: 正版网站设计制作新网站如何做排在前面
- 下一篇: 正保建设教育网站南京马鞍山网站建设
相关文章
-
正版网站设计制作新网站如何做排在前面
正版网站设计制作新网站如何做排在前面
- 技术栈
- 2026年04月20日
-
整站优化提升排名腾讯云怎样做网站
整站优化提升排名腾讯云怎样做网站
- 技术栈
- 2026年04月20日
-
整站优化快速排名wordpress评论验证码
整站优化快速排名wordpress评论验证码
- 技术栈
- 2026年04月20日
-
正保建设教育网站南京马鞍山网站建设
正保建设教育网站南京马鞍山网站建设
- 技术栈
- 2026年04月20日
-
正规的饰品行业网站开发兰州新区建站
正规的饰品行业网站开发兰州新区建站
- 技术栈
- 2026年04月20日
-
正规的网站制作电话小程序代理是做什么的
正规的网站制作电话小程序代理是做什么的
- 技术栈
- 2026年04月20日






