我是靠谱客的博主 虚拟烧鹅,这篇文章主要介绍IO多路复用技术中的水平触发(level trigger,LT)和边缘触发(edge trigger,ET)技术IO多路复用技术中的水平触发(level trigger,LT)和边缘触发(edge trigger,ET)技术,现在分享给大家,希望可以做个参考。

文章目录

  • IO多路复用技术中的水平触发(level trigger,LT)和边缘触发(edge trigger,ET)技术
    • 1. 什么是水平和边缘触发?
      • 1.1 水平触发
        • 1.1.1 读操作
        • 1.1.2 写操作
      • 1.2 边缘触发 (特指epoll模式下)
        • 1.2.1 读操作
        • 1.2.2 对于写操作
    • 2 水平触发和边缘触发在 select poll epoll 中的应用
      • 2.1 水平触发
        • 2.1.1 select 水平触发具体示例:
        • 2.1.2 poll 水平触发具体示例:
        • 2.1.3 epoll 水平触发具体示例:
      • 2.2 epoll中的边缘触发

IO多路复用技术中的水平触发(level trigger,LT)和边缘触发(edge trigger,ET)技术

在Linux中常用的IO复用技术有 select poll epoll 技术,select和poll只支持LT工作模式,epoll的默认的工作模式是LT模式。

1. 什么是水平和边缘触发?

1.1 水平触发

1.1.1 读操作

对于读操作,只要缓冲内容不为空,LT模式返回读就绪

1.1.2 写操作

对于写操作,只要缓冲区还不满,LT模式会返回写就绪

1.2 边缘触发 (特指epoll模式下)

1.2.1 读操作

  • 当缓冲区由不可读变为可读的时候,即缓冲区由空变为不空的时候。
  • 当有新数据到达时,即缓冲区中的待读数据变多的时候。
  • 当缓冲区有数据可读,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件时。

1.2.2 对于写操作

  • 当缓冲区由不可写变为可写时。
  • 当有旧数据被发送走,即缓冲区中的内容变少的时候。
  • 当缓冲区有空间可写,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLOUT事件时。

2 水平触发和边缘触发在 select poll epoll 中的应用

select和poll只支持LT工作模式,epoll的默认的工作模式是LT模式,这是select poll 和epoll区别之一。

2.1 水平触发

2.1.1 select 水平触发具体示例:

源码:


#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
	fd_set rd;
	struct timeval tv;
	int err;
	FD_ZERO(&rd);
	// 将键盘输入的作为读取的文件描述符,每次输入多个文件描述符
	FD_SET(STDIN_FILENO,&rd);
	
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	char buffer[1024];
	
	while (1) 
	{
		select(1,&rd,NULL,NULL,&tv);
		/*
			每次输入多个字符,但是每次只读取一个字符,说明缓冲区还有别的东西,
			在水平触发下会一直进行触发,直到缓冲区没有内容
		*/
		read(STDIN_FILENO, buffer, 1);
		printf("select trigger n");
	}
	return 0;
}

编译执行如下:


# ./selsect
abcd   // 输入字符 abcdn 所以会触发5次
select trigger 
select trigger 
select trigger 
select trigger 
select trigger

2.1.2 poll 水平触发具体示例:

源码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <unistd.h>

int main(void)
{
	struct pollfd * pollFd;
	char buffer[1024];
	pollFd = malloc(sizeof(struct pollfd) * 1);
	// 将键盘输入的作为读取的文件描述符,每次输入多个文件描述符
	pollFd[0].fd = STDIN_FILENO;
	pollFd[0].events = POLLIN;
	int ready = 0;
	while(1)
	{
		ready = poll(pollFd,1,-1);
		printf("poll() trigger returned %dn",ready);
	
		for(int i = 0;i < 1;i++)
		{
			if(pollFd[i].revents & POLLIN)
			{
				/*
					每次输入多个字符,但是每次只读取一个字符,说明缓冲区还有别的东西,
					在水平触发下会一直进行触发,直到缓冲区没有内容
				*/
				read(STDIN_FILENO, buffer, 1);
			}
		}
	}
	return 0;

}

编译运行如下:

root@wan:/wan/15.fly_in_coding/epoll# ./poll
abcd
poll() trigger returned 1
poll() trigger returned 1
poll() trigger returned 1
poll() trigger returned 1
poll() trigger returned 1

2.1.3 epoll 水平触发具体示例:

源码:


#include <unistd.h>
#include <stdio.h>
#include <sys/epoll.h>

int epoll_level_trigger()
{
	int epfd, nfds;
	char buffer[256];
	struct epoll_event event, events[5];
	epfd = epoll_create(1);
	// 将键盘输入的作为读取的文件描述符,每次输入多个文件描述符
	event.data.fd = STDIN_FILENO;
	event.events = EPOLLIN;  // 默认就是水平触发模式
	epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
	while (1) 
	{
		nfds = epoll_wait(epfd, events, 5, -1);
		int i;
		for (i = 0; i < nfds; ++i) 
		{
			if (events[i].data.fd == STDIN_FILENO) 
			{
				/*
					每次输入多个字符,但是每次只读取一个字符,说明缓冲区还有别的东西,
					在水平触发下会一直进行触发,直到缓冲区没有内容
				*/
				read(STDIN_FILENO, buffer, 1);
				printf("epoll level trigger n");
			}
		}
	}
	return 0;
}


int main()
{
	return epoll_level_trigger();
}

编译运行如下:


# ./LT
abcd
epoll level trigger 
epoll level trigger 
epoll level trigger 
epoll level trigger 
epoll level trigger

2.2 epoll中的边缘触发

源码:


/*
源码中的三个函数分别代表上面介绍的边缘触发的三种条件


*/


#include <unistd.h>
#include <stdio.h>
#include <sys/epoll.h>

int epoll_edge_trigger_case1()
{
	int epfd, nfds;
	char buffer[1024];
	struct epoll_event event, events[5];
	epfd = epoll_create(1);
	// 将键盘输入的作为读取的文件描述符,每次输入多个文件描述符
	event.data.fd = STDIN_FILENO;
	event.events = EPOLLIN | EPOLLET;;  // 默认就是水平触发模式,必须显式指定为边缘触发
	epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
	while (1) 
	{
		nfds = epoll_wait(epfd, events, 5, -1);
		int i;
		for (i = 0; i < nfds; ++i) 
		{
			if (events[i].data.fd == STDIN_FILENO) 
			{
				/*
					每次输入多个字符,但是每次只读取一个字符,说明缓冲区还有别的东西,
					但是在边缘触发下不会再次进行发。
					如果应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件时,则会进行再次触发

					具体示例如下 epoll_edge_trigger_case2
				*/
				read(STDIN_FILENO, buffer, 1);
				printf("epoll level trigger n");
			}
		}
	}
	return 0;
}


int epoll_edge_trigger_case2()
{
	int epfd, nfds;
	char buffer[1024];
	struct epoll_event event, events[5];
	epfd = epoll_create(1);
	// 将键盘输入的作为读取的文件描述符,每次输入多个文件描述符
	event.data.fd = STDIN_FILENO;
	event.events = EPOLLIN | EPOLLET;;  // 默认就是水平触发模式,必须显式指定为边缘触发
	epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
	while (1) 
	{
		nfds = epoll_wait(epfd, events, 5, -1);
		int i;
		for (i = 0; i < nfds; ++i) 
		{
			if (events[i].data.fd == STDIN_FILENO) 
			{	
				// 不进行读取,从键盘从不断键入字符,从而让缓冲区内容不断增多
				printf("epoll level trigger n");
			}
		}
	}
	return 0;
}




int epoll_edge_trigger_case3()
{
	int epfd, nfds;
	char buffer[1024];
	struct epoll_event event, events[5];
	epfd = epoll_create(1);
	// 将键盘输入的作为读取的文件描述符,每次输入多个文件描述符
	event.data.fd = STDIN_FILENO;
	event.events = EPOLLIN | EPOLLET;;  // 默认就是水平触发模式,必须显式指定为边缘触发
	epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
	while (1) 
	{
		nfds = epoll_wait(epfd, events, 5, -1);
		int i;
		for (i = 0; i < nfds; ++i) 
		{
			if (events[i].data.fd == STDIN_FILENO) 
			{
				/*
					每次输入多个字符,但是每次只读取一个字符,说明缓冲区还有别的东西,
					在水平触发下会一直进行触发,直到缓冲区没有内容
				*/
				read(STDIN_FILENO, buffer, 1);
                event.events = EPOLLIN | EPOLLET;
                epoll_ctl(epfd, EPOLL_CTL_MOD, STDIN_FILENO, &event);
				printf("epoll level trigger n");
			}
		}
	}
	return 0;
}




int main()
{
	return epoll_edge_trigger_case1();
}

编译运行如下:


# ./LT1
abcd
epoll level trigger

# ./LT2
abcd
epoll level trigger 
abcd
epoll level trigger

# ./LT3   
abcd
epoll level trigger 
epoll level trigger 
epoll level trigger 
epoll level trigger 
epoll level trigger 

最后

以上就是虚拟烧鹅最近收集整理的关于IO多路复用技术中的水平触发(level trigger,LT)和边缘触发(edge trigger,ET)技术IO多路复用技术中的水平触发(level trigger,LT)和边缘触发(edge trigger,ET)技术的全部内容,更多相关IO多路复用技术中的水平触发(level内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(157)

评论列表共有 0 条评论

立即
投稿
返回
顶部