我是靠谱客的博主 虚拟烧鹅,最近开发中收集的这篇文章主要介绍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 trigger,LT)和边缘触发(edge trigger,ET)技术IO多路复用技术中的水平触发(level trigger,LT)和边缘触发(edge trigger,ET)技术所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复