Linux-视频监控系统(2)-Epoll的介绍及使用

1、什么是Epoll

1.1阻塞型IO和多路复用

假如说现在有一个进程需要对设备进行读写,但是这个过程一般需要时间不能马上完成,为了节约CPU资源,这时候一般进程都采取阻塞的方法,把自己挂起,等有设备已经完成操作了再自行其他程序。这种等待方法叫做阻塞型IO


假如一个进程需要同时对4个设备文件进行监控,比如说需要监控打印机有没有打印完成、键盘有没有输入数据,这个过程就叫做多路复用。


那么哪个函数可以既可以实现阻塞型IO又可以实现多路复用呢?
select函数,下面是select函数的使用复习
1、初始化需要操作的文件集合FD_ZERO(&set)
2、把文件描述符一个一个的加到集合中,FD_SET
3、调用select,开始监控,如果没有文件符合会阻塞在这里,直到超时或者有文件满足要求,然后继续运行
4、遍历每个文件,找到哪个文件发生了变化
那么select存在哪些缺点呢?在最后遍历文件的过程中,是极其耗费时间的过程如果文件太多,那这对资源更是一个极大的浪费。

 

所以这里引入Epoll函数,它同样可以实现阻塞和多路复用,同时不需要遍历所有文件就可以知道是哪个文件发生了什么变化,比如说文件里面已经有数据了可以唤醒应用程序来读,比如说应用程序要求写入的数据已经写入了,可以继续做下面的事情了。。而且Epoll可以监控的文件是没有上限的!

 

 

2、怎么使用Epoll

但是要注意Epoll支持管道,FIFO,套接字,POSIX消息队列,终端,设备等,但就是不支持普通文件!!!比如说文件文件,MP3文件等普通文件它都不支持。


Epoll的使用分为3个环节。
epoll_create/epoll_create1 (创建epoll监听池)
epoll_ctl (添加要监听的事件)
epoll_wait (等待事件的发生)

 

epoll_create

在Linux下man一下这个函数:
epoll_create是创建一个监听池,在2.8之前的内核版本中它表明监听文件的数量,在2.8以后的版本中没有任何意义。
epoll_create1有一个flags的参数,当参数为0时和epoll_create函数是一样的同时这个函数的返回值就是监听池的描述符。

 

epoll_ctl

 

添加要监听的事件,比如说添加A文件可读、添加A文件可写,当事件发生时可以立马知道是哪个事件发生了什么操作,所以不再需要遍历所有文件了。
它的原型是:
int epoll_ctl(int enfd, int op, int fd, struct epoll event *event)
第一个参数是监听池的fd,第二个参数是操作的类型比如加入事件、取出事件、删除事件、修改事件等,第三个是事件所对应文件的fd,第四个是事件类型,
struct epoll_event {
__uint32_t events
epoll data data;
};
第一个是事件的类型比如读写,EPOLLIN、EPOLLOUT。


返回值是int类型,成功返回0,失败返回-1

 

epoll_wait 

 

等待事件的发生,它的原型是
int epoll_wait (int epfd, struct epoll_event *events,
                int maxevent,int timeout)
第一个参数是epfd,第二个参数存放发生事件的指针,当事件发生后会把对应文件的操作事件写入这个数组。第四个是最大事件的数组,第五个是超时时间。


那么在摄像头监控系统中存在哪些需要等待的事情呢?
1、摄像头存在一帧新的图像(可读)
2、socket可以发送数据(可写)
3、socket可以接收数据(可读)

因此在我们的监控系统中非常有必要引入Epoll框架程序

 

下面写一个简单的程序来使用Epoll:

 

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/epoll.h>

int main()
{
	int fd1,fd2;
	int ep_fd;
	struct epoll_event event;
	struct epoll_event *events;
	int n,i;
	char c;
	

	mkfifo("/tmp/fifo1",0666);
	mkfifo("/tmp/fifo2",0666);

	fd1 = open("/tmp/fifo1",O_RDONLY);
	fd2 = open("/tmp/fifo2",O_RDONLY);

	ep_fd = epoll_create1(0);
	
	event.events = EPOLLIN | EPOLLET;
	event.data.fd = fd1;
	epoll_ctl(ep_fd, EPOLL_CTL_ADD, fd1, &event);

	event.events = EPOLLIN | EPOLLET;
	event.data.fd = fd2;
	epoll_ctl(ep_fd, EPOLL_CTL_ADD, fd2, &event);

	events = calloc(100, sizeof(event));

	n = epoll_wait(ep_fd, events, 100, -1);
	for(i=0; i<n; i++)
	{
		if(events[i].events & EPOLLIN)
		{
			read(events[i].data.fd, &c, 1);
			printf("file %d read %c!\n",events[i].data.fd,c);
		}
		if(events[i].events & EPOLLOUT)
		{

		}
	}

	close(fd1);
	close(fd2);
	close(ep_fd);
	return 0;
}

 

 

然后编写一个fifo读写的程序:

 

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/epoll.h>

int main()
{
	int fd;
	char c = 'x';	
	fd = open("/tmp/fifo1", O_WRONLY);
	write(fd, &c, 1);
	
	close(fd);

	return 0;
}

同样写出对另一个fifo2文件的读写程序。

 

然后编译后依次运行这几个文件,如果写入数据后ep文件打印出对于的字符即编写成功。

 

更多Linux资料及视频教程点击这里

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值