概述
Android的Looper机制中,MessageQueue阻塞的方式是通过Linux的epoll机制,IO多路复用机制,这里不说原理,说一下epoll使用机制,还是参数的解析。
实例代码
#include <jni.h>
#include <string>
#include <pthread.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <android/log.h>
#define TAG "NATIVE-LIB"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define POLL_WAITING_TIME -1
#define POLL_MAX_SIZE 1
#define POLL_WAIT_MAX_SIZE 10
int error;
int fd[2];
int epoll_fd = 0;
int running = 0;
static void* native_thread(void* args) {
LOGI("启动线程 -------------------- ");
error = pipe(fd);
LOGI("pipe结果 : -------------------- %d", error);
epoll_fd = epoll_create(POLL_MAX_SIZE);
struct epoll_event ev, events[POLL_WAIT_MAX_SIZE];
ev.events = EPOLLIN;
ev.data.fd = fd[0];
error = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd[0], &ev);
LOGI("epoll_ctl结果 : -------------------- %d", error);
running = 1;
while (running) {
LOGI("等待输入数据 -------------------- ");
int count = epoll_wait(epoll_fd, events, POLL_WAIT_MAX_SIZE, POLL_WAITING_TIME);
if (count == 0) {
LOGI("等待超时 -------------------- ");
} else {
LOGI("发现输入数据 -------------------- %d", count);
int data[1];
for (int i = 0; i < count; i++) {
if (events[i].data.fd == fd[0] && events[i].events & EPOLLIN) {
read(events[i].data.fd, data, sizeof(data));
LOGI("输入数据值 : -------------------- %d", data[0]);
}
}
}
}
running = false;
close(fd[0]);
close(fd[1]);
LOGI("停止线程 -------------------- ");
}
extern "C"
JNIEXPORT void JNICALL
Java_com_johan_epoll_EPollNative_00024Companion_start(JNIEnv *env, jobject thiz) {
if (running == 1) {
return;
}
pthread_t id;
pthread_create(&id, NULL, native_thread, NULL);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_johan_epoll_EPollNative_00024Companion_stop(JNIEnv *env, jobject thiz) {
running = 0;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_johan_epoll_EPollNative_00024Companion_notify(JNIEnv *env, jobject thiz, jint number) {
int data[1];
data[0] = number;
if (running) {
error = write(fd[1], data, sizeof(data));
LOGI("写入数据值 : -------------------- %d, %d, %d, %d", fd, data[0], sizeof(data), error);
}
}
epoll相关函数解析
// 头文件
#include <sys/epoll>
如果要使用epoll机制,头文件必须引用
// 表示创建一个epoll句柄
int epoll_create(int _size)
// 对上述创建的epoll句柄进行操作
int epoll_ctl(int __epoll_fd, int __op, int __fd, struct epoll_event* __event);
- __epoll_fd :epoll句柄,也就是epoll_create返回的值
- __op :本次的操作
EPOLL_CTL_ADD:向epoll句柄注册一个fd
EPOLL_CTL_MOD:向epoll句柄修改一个已经注册的fd
EPOLL_CTL_DEL:删除一个已经注册在epoll句柄中的fd - __fd :被监听的文件描述符
- __event :事件结构体
struct epoll_event {
uint32_t events;
epoll_data_t data;
}
- events :被监听的事件
EPOLLIN:表示被监听的fd有可以读的数据
EPOLLOUT:表示被监听的fd有可以写的数据
EPOLLPRI:表示有可读的紧急数据
EPOLLERR:对应的fd发生异常
EPOLLHUP:对应的fd被挂断
EPOLLET:设置EPOLL为边缘触发
EPOLLONESHOT:只监听一次 - data :我们只需要设置data.fd就行了,data.fd参数值就是上面的fd参数值
// 等待处于epoll上被监听的fd产生对应的事件
int epoll_wait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms);
- __epoll_fd :epoll句柄,也就是epoll_create返回的值
- __events :事件数组,触发事件时,会保存到这个数组供我们使用,只要声明就行了,是一个数组
- __event_count :最大响应事件数量
- __timeout_ms :最大等待时长,单位ms,如果不要超时,设置为0
pipe相关参数解析
pipe为管道,调用pipe系统函数即可创建一个管道。有如下特质:
-
其本质是一个伪文件(实为内核缓冲区)
-
由两个文件描述符引用,一个表示读端,一个表示写端。
-
规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
实例这里有使用到,稍微说一下,需要知道的是,创建是一读一写,所以会声明2个fd,也就是fd[2],想知道更详细需要查阅相关文档;
参考
Android 消息处理以及epoll机制
浅谈Android之Linux pipe/epoll
最后
以上就是兴奋老虎为你收集整理的epoll使用实例的全部内容,希望文章能够帮你解决epoll使用实例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复