IO多路复用

一、select

1、创建文件描述符

fd_set rdfds;
fd_set tmpfds;

2、select 函数

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

 宏:

void FD_CLR(int fd, fd_set *set):将fd从文件描述符集合中清除

int  FD_ISSET(int fd, fd_set *set):判断文件描述符fd是否仍在文件描述符集合中

void FD_SET(int fd, fd_set *set):将fd加入文件描述符集合中

void FD_ZERO(fd_set *set):文件描述符集合清0 

 3、缺点

1.select监听文件描述符最大个数为1024 (数组)  O(n)

2.select监听的文件描述符集合在用户层,需要应用层和内核层互相传递数据

3.select需要循环遍历一次才能找到产生的事件

4.select只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)

二、poll

 缺点:

1.poll监测文件描述符不受上限限制  (链表)   O(n)

2.poll监听的文件描述符集合在用户层,需要内核层向用户层传递数据

3.poll需要循环遍历一次才能找到产生的事件

4.poll只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式) 

三、epoll

1. 创建文件描述符集合                  int epoll_create(int size);

2. 添加文件描述符到集合中           epoll_ctl()

3. 通知内核开始监测                     epoll_wait()

4. 根据返回的结果做对应的操作(对io读、写操作)

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

功能:

参数:
          epfd:文件描述符集合句柄
          op: 
                   EPOLL_CTL_ADD: 向集合中添加文件描述符
                   EPOLL_CTL_MOD: 修改集合
                   EPOLL_CTL_DEL :删除文件描述符
          
          fd :操作的文件描述符
         event :文件描述符所对应的事件

int epoll_add_fd(int epfds, int fd, uint32_t event)
{
	struct epoll_event ev;
	ev.events = event;
	ev.data.fd = fd;
	int ret = epoll_ctl(epfds, EPOLL_CTL_ADD, fd, &ev);
	if (-1 == ret)
	{
		perror("fail epoll_ctl add");
		return -1;
	}
	
	return 0;
}

int epoll_del_fd(int epfds, int fd)
{
	int ret = epoll_ctl(epfds, EPOLL_CTL_DEL, fd, NULL);
	if (-1 == ret)
	{
		perror("fail epoll_ctl del");
		return -1;
	}

	return 0;
}

int main(int argc, const char *argv[])
{
	int maxfd = 0;
	char buff[1024] = {0};
	mkfifo("./myfifo", 0664);
	

	int fifofd = open("./myfifo", O_RDONLY);
	if (-1 == fifofd)
	{
		perror("fail open fifo");
		return -1;
	}

	struct epoll_event evs[2];
	int epfds = epoll_create(2);
	if (-1 == epfds)
	{
		perror("fail epoll_create");
		return -1;
	}
	
	epoll_add_fd(epfds, 0, EPOLLIN);
	epoll_add_fd(epfds, fifofd, EPOLLIN);

	while (1)
	{
		int cnt = epoll_wait(epfds, evs, 2, -1);
		if (cnt < 0)
		{
			perror("fail epoll_wait");
			return -1;
		}
		for (int i = 0; i < cnt; i++)
		{
			if (0 == evs[i].data.fd)
			{
				memset(buff, 0, sizeof(buff));
				fgets(buff, sizeof(buff), stdin);
				printf("STDIN: %s\n", buff);
			}
			else if (fifofd == evs[i].data.fd)
			{
				memset(buff, 0, sizeof(buff));
				ssize_t size = read(evs[i].data.fd, buff, sizeof(buff));
				if (size <= 0)
				{
					epoll_del_fd(epfds, evs[i].data.fd);
					close(evs[i].data.fd);
					continue;
				}
				printf("FIFO: %s\n", buff);
			}
		}
	}
	return 0;
}

优点:    1.epoll创建内核事件表,不受到文件描述符上限限制    (红黑树)  O(logn)        
            2.epoll监听的事件表在内核中,直接在内核中监测事件效率高
            3.epoll会直接获得产生事件的文件描述符的信息,而不需要遍历检测 
            4.epoll既能工作在水平触发模式,也能工作在边沿触发模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值