Android的Looper机制中,MessageQueue阻塞的方式是通过Linux的epoll机制,IO多路复用机制,这里不说原理,说一下epoll使用机制,还是参数的解析。
#include
#include
#include
#include
#include
#include
#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);
}
}
// 头文件
#include
如果要使用epoll机制,头文件必须引用
// 表示创建一个epoll句柄
int epoll_create(int _size)
// 对上述创建的epoll句柄进行操作
int epoll_ctl(int __epoll_fd, int __op, int __fd, struct epoll_event* __event);
struct epoll_event {
uint32_t events;
epoll_data_t data;
}
// 等待处于epoll上被监听的fd产生对应的事件
int epoll_wait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms);
pipe为管道,调用pipe系统函数即可创建一个管道。有如下特质:
其本质是一个伪文件(实为内核缓冲区)
由两个文件描述符引用,一个表示读端,一个表示写端。
规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
实例这里有使用到,稍微说一下,需要知道的是,创建是一读一写,所以会声明2个fd,也就是fd[2],想知道更详细需要查阅相关文档;