中国咖啡网站建设方案,专门做门的网站,wordpress多站点怎么修改域名,株洲公司做网站一、select和epoll原理分析
外设设备网卡、鼠标、键盘等通过总线写到内存中#xff0c;中间就有DMA拷贝#xff0c;操作系统怎么知道内存中有数据了#xff0c;这就需要操作系统通过中断机制确定#xff0c;如果有中断信号过来#xff0c;cpu会首先打断用户程序执行…一、select和epoll原理分析
外设设备网卡、鼠标、键盘等通过总线写到内存中中间就有DMA拷贝操作系统怎么知道内存中有数据了这就需要操作系统通过中断机制确定如果有中断信号过来cpu会首先打断用户程序执行响应硬件的程序的信号然后再恢复用户程序的执行不同外设设备对应的驱动程序不同发送的中断信号也就不同操作系统根据对应信号做出相应的处理
1、操作系统如何处理中断请求
内核和设备驱动是通过中断方式来处理的。所谓中断可以理解当设备上有数据到达时会给cpu的相关引脚上发一个电压变化以通知cpu来处理数据硬件产生的信号需要cpu立马处理否则数据可能丢失 网络模块比较耗时中断时会过度占用cpu导致cpu无法响应其它设备因此在Linux中段处理函数分上半部和下半部上半部通知cpu下半部响应 2、进程阻塞
操作系统为了支持多任务实现进程调度功能会把进程分为“运行”和“等待”等几种状态。运行状态是获取cpu使用权正在执行的代码是运行状态等待状态是阻塞状态详情参照下图个人理解 3、内核接收网络数据
一旦有cpu响应中断操作就会拷贝数据到内存经过协议层的解析到socket应用层就有了数据就会唤醒进程A重新进入到工作队列中 4、同时监视多个socket的简单方法
select实现思路很直接。假如程序同时监视socket1、socket2、socket3那么调用select之后操作系统把进程A分别加入到这三个socket的等待列表中当任何一个socket收到数据都会中断程序唤醒进程A所有的socket的等待队列中的进程A都会被移除加入到工作队列中 如上图所示进程A只知道Socket有数据过来并不知道哪些Socket有数据所以就需要遍历Socket列表并且处于遍历的性能考虑select最大只能监视1024个Socket
5、epoll的原理
当执行epoll_create方法时内核会创建一个eventpoll对象当Socket收到数据后中断程序会操作eventpoll对象而不直接操作进程中断程序会给rdlist引用收到的数据Socket2、Socket3当执行epoll_wait如果rdlist已经引用了Socket那么epoll_wait直接返回如果rdlist为空阻塞进程 当Socket接收到数据中断程序一方面修改rdlist另一个方面唤醒 eventpoll等待队列的线程线程A回到工作队列中去由于rdlist引用了接收了数据的Socket所以不用对所有的进行遍历
二、Netty基础
1、Netty的组件
Bootstrap是Netty框架的启动类和主入口类分为客户端类Bootstrap和服务器类ServerBootstrap两种。EventLoop暂时可以看成一个线程、EventLoopGroup 自然就可以看成线程组。Channel是Java NIO的一个基本构造。ChannelHandler和ChannelPipeline每个事件都可以被分发给 ChannelHandler 类中的某个用户实现的方法既然事件分为 入站和出站用来处理事件的 ChannelHandler 也被分为可以处理入站事件的 Handler 和出站 事件的 Handler当然有些 Handler 既可以处理入站也可以处理出站这些 ChannelHandler 都放在 ChannelPipeline 中统一管理ChannelFuture异步获取结果的类类似于JDK的java.util.concurrent.Future类
2、使用示例
dependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion4.1.42.Final /versionscopecompile/scope
/dependency
服务端
public class EchoServer {private static final Logger LOG LoggerFactory.getLogger(EchoServer.class);private final int port;public EchoServer(int port) {this.port port;}public static void main(String[] args) throws InterruptedException {int port 9999;EchoServer echoServer new EchoServer(port);LOG.info(服务器即将启动);echoServer.start();LOG.info(服务器关闭);}public void start() throws InterruptedException {/*线程组*/EventLoopGroup group new NioEventLoopGroup();try {/*服务端启动必备*/ServerBootstrap b new ServerBootstrap();b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializerSocketChannel() {Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoServerHandler());}});/*异步绑定到服务器sync()会阻塞到完成*/ChannelFuture f b.bind().sync();LOG.info(服务器启动完成。);/*阻塞当前线程直到服务器的ServerChannel被关闭*/f.channel().closeFuture().sync();} finally {group.shutdownGracefully().sync();}}}
客户端
public class EchoClient {private final int port;private final String host;public EchoClient(int port, String host) {this.port port;this.host host;}public void start() throws InterruptedException {/*线程组*/EventLoopGroup group new NioEventLoopGroup();try {/*客户端启动必备和服务器的不同点*/Bootstrap b new Bootstrap();b.group(group).channel(NioSocketChannel.class)/*指定使用NIO的通信模式*//*指定服务器的IP地址和端口和服务器的不同点*/.remoteAddress(new InetSocketAddress(host,port))/*和服务器的不同点*/.handler(new ChannelInitializerSocketChannel() {Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoClientHandler());}});/*异步连接到服务器sync()会阻塞到完成和服务器的不同点*/ChannelFuture f b.connect().sync();f.channel().closeFuture().sync();/*阻塞当前线程直到客户端的Channel被关闭*/} finally {group.shutdownGracefully().sync();}}public static void main(String[] args) throws InterruptedException {new EchoClient(9999,127.0.0.1).start();}
}
服务端的ChannelHandler
public class EchoServerHandler extends ChannelInboundHandlerAdapter {Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf in (ByteBuf)msg;System.out.println(server accept : in.toString(CharsetUtil.UTF_8));ctx.writeAndFlush(in);//ctx.close();}Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println(连接已建立);super.channelActive(ctx);}Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
客户端的ChannelHandler
public class EchoClientHandler extends SimpleChannelInboundHandlerByteBuf {/*读取到网络数据后进行业务处理,并关闭连接*/Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {System.out.println(client Acceptmsg.toString(CharsetUtil.UTF_8));//关闭连接///ctx.close();}/*channel活跃后做业务处理*/Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer(Hello,Netty,CharsetUtil.UTF_8));
// ctx.pipeline().write()
// ctx.channel().write()ctx.alloc().buffer();}
}