IO复用

Linux 数据通信之IO复用模块

概念

  • 单个句柄占用一个输入 输出 造成资源过剩,使用文件集合占用一个输入输出

方法

  • select
  • poll
  • epoll

select IO 复用手段

  • 对象–>fd_set 文件集合
  • 使用领域
  • IO复用流程
  1. struct fd_set
  • 分配 struct fd_set rfds;

  • 设置
    初始化 FD_ZERO(&rfds);
    加入句柄 FD_SET(fd, &rfds);
    移除句柄 FD_CLR(int fd, fd_set *set);

  • 使用
    int select(int nfds, fd_set *readfds, fd_set *writefds,
    fd_set *exceptfds, struct timeval *timeout);

    int nfds 文件集合中最大的fd+1
    struct timeval timeout
    struct timeval {
    long tv_sec; /
    seconds /
    long tv_usec; /
    microseconds */
    };

    判断由哪个fd引起的返回 int FD_ISSET(int fd, fd_set *set);

  1. 使用方法
    首先进行select 等待
    accept
  • 注意: 每次重新发起select时,需要对fd_set重新添加
IO复用流程
select demo演示
	/* According to POSIX.1-2001 */
	#include <sys/select.h>
	
	/* According to earlier standards */
	#include <sys/time.h>
	#include <sys/types.h>
	#include <unistd.h>
使用场合

服务器:
tcp 与 udp同时进行监听
既作为服务器 又作为客户端 代理 select
客户端:
监听多个句柄时() 1000

stdin
fd 进程间通信句柄
socket

poll机制
  • 分析和已有模型的区别
    select —>fd_set包含需要进行IO复用的句柄
    poll ---->pollfd包含需要进行IO复用的句柄 pollfd句柄链表 句柄链表的头
  • 对象
struct pollfd{
	int fd;  //当前的处理句柄
	short events; 句柄关心的事件
	short revents;
}

event
/* These are specified by iBCS2 */
#define POLLIN		0x0001
#define POLLPRI		0x0002
#define POLLOUT		0x0004
#define POLLERR		0x0008
#define POLLHUP		0x0010
#define POLLNVAL	0x0020

listen_fd

pollfd 
 .fd = listen_fd
 .events = POLLIN | POLLPRI 
int poll(struct pollfd *fds, nfds_t nfds, int timeout);





/* The rest seem to be more-or-less nonstandard. Check them! */
#define POLLRDNORM	0x0040
#define POLLRDBAND	0x0080
#ifndef POLLWRNORM
#define POLLWRNORM	0x0100
#endif
#ifndef POLLWRBAND
#define POLLWRBAND	0x0200
#endif
#ifndef POLLMSG
#define POLLMSG		0x0400
#endif
#ifndef POLLREMOVE
#define POLLREMOVE	0x1000
#endif
#ifndef POLLRDHUP
#define POLLRDHUP       0x2000
#endif

#define POLLFREE	0x4000	/* currently only for epoll */

#define POLL_BUSY_LOOP	0x8000


revents 回复事件
事件返回指针 	
struct pollfd;
pollfd.fd
pollfd.event
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

revents
struct pollfd{
	int fd;  //当前的处理句柄
	short events; 句柄关心的事件
	short revents;
}


fd_set  pollfd
  1. 使用poll select 实现回射服务器(客户端发什么 服务端回什么)
    要求:客户端和服务端都需要使用select的机制
  2. 设计一个tcp的代理

select 与 poll的内核机制分析
select poll
int 80 systemcall
__syscall_start
sys_select
core_sys_select
do_select
*timeout -= __timeout;
const struct file_operations *f_op;
unsigned int (*poll) (struct file *, struct poll_table_struct *);
f_op->poll —>mask
unsigned int datagram_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
unsigned int mask;

poll_wait(file, sk->sk_sleep, wait);
mask = 0;

/* exceptional events? */
if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
	mask |= POLLERR;
if (sk->sk_shutdown & RCV_SHUTDOWN)
	mask |= POLLRDHUP;
if (sk->sk_shutdown == SHUTDOWN_MASK)
	mask |= POLLHUP;

/* readable? */
if (!skb_queue_empty(&sk->sk_receive_queue) ||
    (sk->sk_shutdown & RCV_SHUTDOWN))
	mask |= POLLIN | POLLRDNORM;

/* Connection-based need to check for termination and startup */
if (connection_based(sk)) {
	if (sk->sk_state == TCP_CLOSE)
		mask |= POLLHUP;
	/* connection hasn't started yet? */
	if (sk->sk_state == TCP_SYN_SENT)
		return mask;
}

/* writable? */
if (sock_writeable(sk))
	mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
else
	set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);

return mask;

}

epoll

  • 并发性高,可同时监听C10K以上级别的客户事件
    select ----> fd—>fd_set --轮训
    poll ---- fd—>pollfd
    epoll ----> fd—event
    epoll : 大规模并发服务框架
    epoll+threadpool+mysql
  • 对象
    epoll_fd epoll_event
创建 epollfd对象:
	int epoll_create(int size); 返回值 epoll_fd epoll_event
设置 epollfd对象:
	创建 epoll_event对象
		 struct epoll_event ep_ev;
	设置 epoll_event对象
		   ep_ev.events = EPOLLIN;//数据的读取
    	   ep_ev.data.fd = listen_sock;	
	使用 epoll_event对象
		  epoll_ctl(int epfd,int op, int fd, struct epoll_event *event);
		  epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_sock,&ep_ev);
使用epollefd对象: 
	 int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
// 第二个struct epoll_event *events是用来做返回的
// maxevents 
// timeout




typedef union epoll_data {
       void    *ptr;
       int      fd;
       uint32_t u32;
       uint64_t u64;
   } epoll_data_t;

   struct epoll_event {
       uint32_t     events;    /* Epoll events */
       epoll_data_t data;      /* User data variable */
   };


epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
EPOLL_CTL_ADD
EPOLL_CTL_MOD
EPOLL_CTL_DEL


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值