Looper 监听文件描述符

Posted Achillisjack

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Looper 监听文件描述符相关的知识,希望对你有一定的参考价值。

还是以SurfaceFlinger为例论述。SurfaceFlinger的init方法会调用MessageQueue的setEventThread方法创建Connection对象,并且还会调用Looper的addFd方法将BitTube对象的文件描述符添加到Looper中进行监听,

mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
    MessageQueue::cb_eventReceiver, this);

也就是说,一旦BitTube对象的文件描述符发生变化,就会回调MessageQueuecb_eventReceiver方法。

Looper的addFd方法调用流程图如下,


Looper中有2个addFd方法,

return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);

如果callback不为空,就构造SimpleLooperCallback对象, SimpleLooperCallback 是Looper.cpp中的一个类,其构造方法如下,

SimpleLooperCallback::SimpleLooperCallback(Looper_callbackFunc callback) :
        mCallback(callback) 

将回调方法赋值给mCallback变量, Looper.h中的mCallback声明如下,

Looper_callbackFunc mCallback;

addFd方法逻辑如下,

1,为结构体Request 赋值,主要保存文件描述符,回调方法等,

Request request;
request.fd = fd;
request.ident = ident;
request.events = events;
request.seq = mNextRequestSeq++;
request.callback = callback;
request.data = data;

Request 结构体定义在Looper.h中。

2,调用系统的epoll_ctl 方法添加到epoll监控中,并且将request结构体对象添加到mRequests列表中。

int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
•••
mRequests.add(fd, request);

根据Looper机制,消息处理最后会调用Looper的pollOnce方法,该方法处理回调流程图如下,


pollInner方法主要逻辑如下,

1,调用系统的epoll_wait方法等待epoll事件的到来,也就是BitTube 对应文件值发生变化,

int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

2,调用SimpleLooperCallback的handleEvent方法进行回调处理,

int callbackResult = response.request.callback->handleEvent(fd, events, data);

SimpleLooperCallback的handleEvent方法如下,

int SimpleLooperCallback::handleEvent(int fd, int events, void* data) 
    return mCallback(fd, events, data);

直接调用回调方法。此回调方法就是通过addFd方法设置的回调方法。

在此,需要记住的是,通过调用Looper的addFd方法设置方法的回调,如果文件描述符发生变化,就会调用回调方法。

在SurfaceFlinger中,

mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
    MessageQueue::cb_eventReceiver, this);

一旦BitTube对应文件值发生变化,就会回调MessageQueue的cb_eventReceiver方法。

除了SurfaceFlinger 使用了这种机制之外,在android系统中,还有很多地方都使用了这个机制。

例如,按键/消息 事件从从驱动到HAL到JNI最后到APP就是通过这种方法监听的,详细请见http://blog.csdn.net/u012439416/article/details/54605324

以上是关于Looper 监听文件描述符的主要内容,如果未能解决你的问题,请参考以下文章

服务器select模型

2. 基于多路复用的服务端

Handler ,MessageQueue 的Looper中epoll监听的fd

Handler ,MessageQueue 的Looper中epoll监听的fd

Oracle ORA12514 监听程序当前无法识别连接描述符中请求的服务

Oracle错误——ORA12514:监听程序当前无法识别连接描述符中请求的服务