1. SylixOS epoll介绍
SylixOS为了兼容Linux的epoll,创建了epoll的兼容子系统,并支持了epoll的部分功能。SylixOS epoll兼容子系统是由select子系统模拟出来的,所以效率没有select高。
2. epoll异常分析
2.1epoll异常场景
在使用线程A创建AF_UNIX匿名套接字发送数据;线程B把套接字加入epoll监听,且设置属性为一次有效;线程C等待epoll事件产生,并读取套接字中的数据。如程序清单 2-1所示。
程序清单 2-1
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/epoll.h>
#define READSIZE 7
int iEfd = 0;
int iFd[2] = {0};
void *send_data (void *arg)
{
int iRet = 0;
/*
* 使用socketpair函数创造一对未命名的、相互连接的UNIX域套接字
* 并且的在一端不断的发送数据
*/
iRet = socketpair(AF_UNIX, SOCK_STREAM, 0, iFd);
if (iRet < 0) {
perror("socketpair");
return NULL;
}
for (;;) {
write(iFd[0], "SylixOS", READSIZE);
sleep(1);
}
}
void *test_ctl(void *arg)
{
struct epoll_event event;
int iRet = 0;
while (1) {
/ *
* 把套接字加入epoll监听,且设置监听属性为一次有效
*/
event.events = 0;
event.events = EPOLLIN | EPOLLONESHOT;
event.data.fd = iFd[1];
iRet = epoll_ctl(iEfd, EPOLL_CTL_MOD, iFd[1], &event);
if (iRet == 0) {
printf("test_ctl ctl ok\n");
}
sleep(1);
}
}
void *test_wait(void *arg)
{
struct epoll_event event;
int iRet = 0;
char cBuf[READSIZE] = {0};
while (1) {
/ *
* 使用epoll等待事件,并读取数据。读取结束后等待下一次事件产生
*/
iRet = epoll_wait(iEfd, &event, 1, -1);
if (iRet == 1) {
printf("test_wait event.data.fd is %d event.events is %x\n",
event.data.fd,event.events);
read(iFd[1], cBuf, READSIZE);
}
sleep(1);
}
}
int main(int argc, char **argv)
{
pthread_t send_tid,
wait_tid,
ctl_tid;
int iRet = 0;
struct epoll_event event;
/*
* 创建一个 epoll 文件描述符
*/
iEfd = epoll_create(10);
if (0 == iEfd) {
perror("epoll create");
return (-1);
}
iRet = pthread_create(&send_tid, NULL, &send_data, NULL);
if (iRet != 0) {
fprintf(stderr, "pthread create failed.\n");
return (-1);
}
sleep(1);
/ *
* 把套接字加入epoll监听,且设置为一次有效
*/
event.events = EPOLLIN | EPOLLONESHOT;
event.data.fd = iFd[1];
iRet = epoll_ctl(iEfd, EPOLL_CTL_ADD, iFd[1], &event);
if (iRet != 0) {
perror("epoll_ctl");
return (-1);
}
iRet = pthread_create(&wait_tid, NULL, &test_wait, NULL);
if (iRet != 0) {
perror("pthread create");
return (-1);
}
iRet = pthread_create(&ctl_tid, NULL, &test_ctl, NULL);
if (iRet != 0) {
perror("pthread create");
return (-1);
}
pthread_join(send_tid, NULL);
pthread_join(wait_tid, NULL);
pthread_join(ctl_tid, NULL);
return (0);
}
该程序运行时,运行结果如图 2-1所示。
图 2-1 运行结果
此时线程test_wait阻塞等待事件产生,根据程序清单 2-1所示,send_data线程一直在写入数据,同时test_ctl线程也在把事件加入epoll中监听。
2.2epoll异常分析
SylixOS epoll兼容子系统是由select子系统模拟出来的,分析epoll_wait源码。epoll_wait代码框架如图 2-2所示。
图 2-2 epoll_wait流程
根据epoll_wait实现流程可以发现,如果在epoll_ctl设置事件属性为一次有效,在epoll_wait后事件属性置空。如果此刻epoll_wait在下次epoll_ctl操作之前使用,那么epoll_wait中监听的文件描述符集合即为空(因为事件属性为空),所以select一直处于监听,且没有事件产生。
3. epoll异常总结
把程序清单 2-1中设置保证epoll_wait在epoll_ctl之后运行,运行结果如图 3-1所示。
图 3-1 运行结果
在SylixOS上使用epoll功能需要注意要保证epoll_wait在epoll_ctl设置之后使用,这样保证epoll_wait监听的文件描述符集合不为空。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。