epoll函数

Java多线程:Linux多路复用,Java NIO与Netty简述

蓝咒 提交于 2020-03-15 10:11:48
JVM的多路复用器实现原理 Linux 2.5以前:select/poll Linux 2.6以后: epoll Windows: Winsock的select模型(感谢评论指正,仅Java NIO.2使用了Windows IOCP,由于Netty没有采用NIO.2此处不展开) Free BSD, OS X: kqueue 下面仅讲解Linux的多路复用。 Linux中的IO Linux的IO将所有外部设备都看作文件来操作,与外部设备的操作都可以看做文件操作,其读写都使用内核提供的系统调用,内核会返回一个文件描述符(fd, file descriptor),例如socket读写使用socketfd。描述符是一个索引,指向内核中一个结构体,应用程序对文件的读写通过描述符完成。 一个基本的IO,涉及两个系统对象:调用这个IO进程的对象,系统内核,read操作发生时流程如下: 通过read系统调用向内核发起读请求。 内核向硬件发送读指令,并等待读就绪。 内核把将要读取的数据复制到描述符所指向的内核缓存区中。 将数据从内核缓存区拷贝到用户进程空间中。 Linux I/O模型简介 阻塞I/O模型:最常用,所有文件操作都是阻塞的。 非阻塞I/O模型:缓冲区无数据则返回,一般采用轮询的方式做状态检查。 I/O复用模型:详细见下 信号驱动I/O:使用信号回调应用,内核通知用户何时开启一个I/O操作

libevent源码剖析

Deadly 提交于 2020-03-14 14:33:40
安装与使用   libevent安装:下载地址: http://libevent.org/ 解压文件:tar -zxvf libevent- 2.1 .8-stable.tar.gz 解压后进入目录,进行配置,把库安装到/usr目录下: ./configure -- prefix= /usr 编译安装:sudo make,sudo make install   libevent将I/O事件、信号事件、定时事件三种事件进行了同一事件源,将所有的就绪事件,放入到激活链表中;然后对激活链表中的事件,调用事件的回调函数执行事件处理 一、event_base   The event_base lies at the center of Libevent; every application will have one.对应的为Reactor实例,使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个event_base 结构体持有一个事件集合,可以检测以 确定哪个事件是激活的(相当于epoll红黑树的树根)。   因为不是所有的安插在event_base的事件在调用fork()之后都可以正常工作,所以,如果在使用fork()或者其他相关系统调用启动一个新的进程之后,要想在子进程中使用base变量,但是又想让该base变量是一个全新的没有安插事件的变量

Java NIO 底层原理

旧城冷巷雨未停 提交于 2020-03-05 10:06:43
目录 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3. 同步阻塞IO(Blocking IO) 1.4. 同步非阻塞NIO(None Blocking IO) 1.5. IO多路复用模型(I/O multiplexing) 1.6. 异步IO模型(asynchronous IO) 小结一下: 本文的知识,在《 Netty Zookeeper Redis 高并发实战 》 1.1. Java IO读写原理 无论是Socket的读写还是文件的读写,在Java层面的应用开发或者是linux系统底层开发,都属于输入input和输出output的处理,简称为IO读写。在原理上和处理流程上,都是一致的。区别在于参数的不同。 用户程序进行IO的读写,基本上会用到read&write两大系统调用。可能不同操作系统,名称不完全一样,但是功能是一样的。 先强调一个基础知识:read系统调用,并不是把数据直接从物理设备,读数据到内存。write系统调用,也不是直接把数据,写入到物理设备。 read系统调用,是把数据从内核缓冲区复制到进程缓冲区;而write系统调用,是把数据从进程缓冲区复制到内核缓冲区。这个两个系统调用,都不负责数据在内核缓冲区和磁盘之间的交换。底层的读写交换

select、poll和epoll的区别和优缺点

陌路散爱 提交于 2020-03-03 18:03:03
原文地址: https://blog.csdn.net/BaiHuaXiu123/article/details/89948037 I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。select,poll,epoll都是IO多路复用的机制。但 select,poll,epoll本质上都是同步I/O ,因为他们都需要在读写事件就绪后自己负责进行读写, 也就是说这个读写过程是阻塞的 ,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。下来,分别谈谈。 select——> 原理概述: select 的核心功能是调用tcp文件系统的poll函数,不停的查询,如果没有想要的数据,主动执行一次调度(防止一直占用cpu),直到有一个连接有想要的消息为止。从这里可以看出select的执行方式基本就是不同的调用poll,直到有需要的消息为止。 缺点: 1、每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大; 2、同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大; 3、select支持的文件描述符数量太小了,默认是1024。 优点: 1、select的可移植性更好,在某些Unix系统上不支持poll()。 2

并发程序设计3:多路IO复用技术(2)

你说的曾经没有我的故事 提交于 2020-02-26 13:09:08
  上一节( https://www.cnblogs.com/yuanwebpage/p/12362876.html )记录了多路IO复用的第一种方式select函数,以及其相应的缺点。本节记录多路IO复用的第二种方式epoll(在windows系统下叫IOCP)。 1. epoll相关函数   epoll函数克服了select函数的相关缺点,其优点如下: (1) 只需向OS注册一次文件描述符集合,不用每次循环传递; (2) epoll函数会将发生变化的文件描述符单独集中起来,这样每次遍历时只需要遍历发生变化的文件描述符。 (3) 相对于select同时监听的数量有限制,epoll监听数量一般远大于select,这对于多连接的服务器至关重要。 epoll用来集中通知变化的文件描述符结构体如下: struct epoll_event { __uint32_t events; //用来注册是什么事件需要关注,如输入/输出 epoll_data_t data; } typedef union epoll_data { void* ptr; int fd; //发生变化的文件描述符 __uint32_t u32; __uint64_t u64; } epoll_data_t; //可以看到,常用的为events, fd两个 epoll相关的函数总共有3个: #include <sys

Linux企业级开发技术(3)——epoll企业级开发之epoll模型

自作多情 提交于 2020-02-25 19:58:50
EPOLL事件有两种模型: Edge Triggered (ET) 边缘触发 只有数据到来,才触发,不管缓存区中是否还有数据。 Level Triggered (LT) 水平触发 只要有数据都会触发。 假如有这样一个例子: 1. 我们已经把一个用来从管道中读取数据的文件句柄(RFD)添加到epoll描述符 2. 这个时候从管道的另一端被写入了2KB的数据 3. 调用epoll_wait(2),并且它会返回RFD,说明它已经准备好读取操作 4. 然后我们读取了1KB的数据 5. 调用epoll_wait(2)...... Edge Triggered 工作模式: 如果我们在第1步将RFD添加到epoll描述符的时候使用了EPOLLET标志,那么在第5步调用epoll_wait(2)之后将有可能会挂起,因为剩余的数据还存在于文件的输入缓冲区内,而且数据发出端还在等待一个针对已经发出数据的反馈信息。只有在监视的文件句柄上发生了某个事件的时候 ET 工作模式才会汇报事件。因此在第5步的时候,调用者可能会放弃等待仍在存在于文件输入缓冲区内的剩余数据。在上面的例子中,会有一个事件产生在RFD句柄上,因为在第2步执行了一个写操作,然后,事件将会在第3步被销毁。因为第4步的读取操作没有读空文件输入缓冲区内的数据,因此我们在第5步调用 epoll_wait(2)完成后,是否挂起是不确定的

Linux企业级开发技术(2)——epoll企业级开发之epoll接口

牧云@^-^@ 提交于 2020-02-25 19:57:22
epoll的接口非常简单,总共只有三个函数: 1、int epoll_create(intsize); 生成一个 Epoll 专用的文件描述符,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。 其实是申请一个内核空间,用来存放你想关注的 socket fd 上是否发生以及发生了什么事件。 size 就是你在这个 Epoll fd 上能关注的最大 socket fd 数,大小自定,只要内存足够。 2、int epoll_ctl(intepfd, int op, int fd, struct epoll_event *event); epoll的事件注册函数,它不同与select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。它用来控制某个epoll 文件描述符上的事件:注册、修改、删除。其中参数 epfd 是 epoll_create() 创建 Epoll 专用的文件描述符。相当于 select 模型中的 FD_SET 和 FD_CLR 宏。 第一个参数是epoll

[C++] epoll server实例

时光毁灭记忆、已成空白 提交于 2020-02-25 19:56:43
// IO多路复用,事件驱动+非阻塞,实现一个线程完成对多个fd的监控和响应,提升CPU利用率 // epoll优点: // 1.select需要每次调用select时拷贝fd,epoll_ctl拷贝一次,epoll_wait就不需要重复拷贝 // 2.不需要像select遍历fd做检查,就绪的会被加入就绪list,遍历list完成处理 // 3.没有最大连接限制,与最大文件数目相关:cat /proc/sys/fs/file-max,与内存相关 // epoll实现相关: // 1.epoll_ctl,将fd的event使用RB tree保存,读写O(logN); // 2.一旦有event,内核负责添加到rdlist链表 // 3.epoll_wait检查链表看是否有事件,并进行处理 // Ref // https://www.cnblogs.com/lojunren/p/3856290.html // http://blog.chinaunix.net/uid-28541347-id-4273856.html // Question: // 是否需要每个event一个实例? #include <cstdlib> /* exit() */ #include <cstdio> /* perror(): 打印信息+发生错误的原因,可用于定位。 */ #include

IO复用解述

寵の児 提交于 2020-02-25 19:54:30
I/O多路复用 select select 允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或指定时间后返回它。 select函数原型 #include <sys/select.h> #include <sys/time.h> int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout); 返回值: 监听到有事件发生的文件描述符的个数,超时为0,错误为 -1. 1.当监视的相应的文件描述符集中满足条件时,比如说读文件描述符集中有数据到来时,内核(I/O)根据状态修改文件描述符集,并返回一个大于0的数。 2.当没有满足条件的文件描述符,且设置的timeval监控时间超时时,select函数会返回一个为0的值。 3.当select返回负值时,发生错误。 参数: maxfd: 是需要监视的最大的文件描述符值+1; rdset、wrset、exset: 是传入传出参数,fd_set类型,分别对应于需要检测的可读文件描述符的集合、可写文件描述符的集合、异常文件描述符的集合。若对其中任何参数条件不感兴趣,则可将其设为NULL。 timeout: 设置超时时间,指定select在返回前没有接收事件时应该等待的时间。 timeval 结构体 struct

I/O多路复用select/poll/epoll

Deadly 提交于 2020-02-25 19:52:32
前言 早期操作系统通常将进程中可创建的线程数限制在一个较低的阈值,大约几百个。因此, 操作系统会提供一些高效的方法来实现多路IO,例如Unix的select和poll。现代操作系统中,线程数已经得到了极大的提升,如NPTL线程软件包可支持数十万的线程。 I/O多路复用 select select 允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或指定时间后返回它。 select函数原型 #include <sys/select.h> #include <sys/time.h> int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout); 返回值: 监听到有事件发生的文件描述符的个数,超时为0,错误为 -1. 1.当监视的相应的文件描述符集中满足条件时,比如说读文件描述符集中有数据到来时,内核(I/O)根据状态修改文件描述符集,并返回一个大于0的数。 2.当没有满足条件的文件描述符,且设置的timeval监控时间超时时,select函数会返回一个为0的值。 3.当select返回负值时,发生错误。 参数: maxfd: 是需要监视的最大的文件描述符值+1; rdset、wrset、exset: 是传入传出参数,fd_set类型