zoukankan      html  css  js  c++  java
  • Android7.0 MessageQueue

    Android中的消息处理机制大量依赖于Handler。每一个Handler都有相应的Looper,用于不断地从相应的MessageQueue中取出消息处理。
    一直以来,觉得MessageQueue应该是Java层的抽象。然而事实上MessageQueue的主要部分在Native层中。
    自己对MessageQueue在Native层的工作不太熟悉,借此机会分析一下。

    一、MessageQueue的创建
    当须要使用Looper时。我们会调用Looper的prepare函数:

    public static void prepare() {
        prepare(true);
    }
    
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //sThreadLocal为线程本地存储区;每一个线程仅有一个Looper
        sThreadLocal.set(new Looper(quitAllowed));
    }
    
    private Looper(boolean quitAllowed) {
        //创建出MessageQueue
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

    1 NativeMessageQueue
    我们看看MessageQueue的构造函数:

    MessageQueue(boolean quitAllowed) {
        mQuitAllowed = quitAllowed;
        //mPtr的类型为long?
        mPtr = nativeInit();
    }

    MessageQueue的构造函数中就调用了native函数,我们看看android_os_MessageQueue.cpp中的实现:

    static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
        //MessageQueue的Native层实体
        NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
        ............
        //这里应该相似与将指针转化成long类型,放在Java层保存;预计Java层使用时,会在native层将long变成指针,就能够操作队列了
        return reinterpret_cast<jlong>(nativeMessageQueue);
    }

    我们跟进NativeMessageQueue的构造函数:

    NativeMessageQueue::NativeMessageQueue() :
            mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
        //创建一个Native层的Looper,也是线程唯一的
        mLooper = Looper::getForThread();
        if (mLooper == NULL) {
            mLooper = new Looper(false);
            Looper::setForThread(mLooper);
        }
    }

    从代码来看,Native层和Java层均有Looper对象。应该都是操作MessageQueue的。MessageQueue在Java层和Native层有各自的存储结构,分别存储Java层和Native层的消息。

    2 Native层的looper

    我们看看Native层looper的构造函数:

    Looper::Looper(bool allowNonCallbacks) :
            mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
            mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
            mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
        //此处创建了个fd
        mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
        .......
        rebuildEpollLocked();
    }

    在native层中,MessageQueue中的Looper初始化时。还调用了rebuildEpollLocked函数,我们跟进一下:

    void Looper::rebuildEpollLocked() {
        // Close old epoll instance if we have one.
        if (mEpollFd >= 0) {
            close(mEpollFd);
        }
    
        // Allocate the new epoll instance and register the wake pipe.
        mEpollFd = epoll_create(EPOLL_SIZE_HINT);
        ............
        struct epoll_event eventItem;
        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
        eventItem.events = EPOLLIN;
        eventItem.data.fd = mWakeEventFd;
        //在mEpollFd上监听mWakeEventFd上是否有数据到来
        int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
        ...........
        for (size_t i = 0; i < mRequests.size(); i++) {
            const Request& request = mRequests.valueAt(i);
            struct epoll_event eventItem;
            request.initEventItem(&eventItem);
            //监听request相应fd上数据的到来
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
            ............
        }
    }

    从native层的looper来看,我们知道Native层依赖于epoll来驱动事件处理。此处我们先保留一下大致的映像。后文具体分析。

    二、使用MessageQueue
    1 写入消息
    Android中既能够在Java层向MessageQueue写入消息。也能够在Native层向MessageQueue写入消息。我们分别看一下相应的操作流程。

    1.1 Java层写入消息
    Java层向MessageQueue写入消息,依赖于enqueueMessage函数:

    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
    
        synchronized (this) {
            if (mQuitting) {
                .....
                return false;
            }
    
            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                //在头部插入数据,假设之前MessageQueue是堵塞的,那么如今须要唤醒
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                // 若MessageQueue当前处于堵塞状态,而且新增加的消息为异步消息。而且异步消息的target等于null。那么有可能唤醒MessageQueue
                // 注意有两种方式创建一个消息是异步:
                // 1、创建一个异步的handler,我们经常使用的用looper构造的Handler是同步的。

    用异步的handler发送消息,消息将被设置为异步的; // 2、创建一个Message,调用Message的setAsynchronous将该Message指定为异步的 // 考虑到MessageQueue的enqueueMessage函数,要求target必须不等于null。因此这里的needWake应该一直是false needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } //若needWake为true(应该不会出现这样的情况),但新增加的消息不是第一个异步消息时,needWake又一次置为false if (needWake && p.isAsynchronous()) { needWake = false; } } msg.next = p; // invariant: p == prev.next prev.next = msg; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; }

    上述代码比較简单,主要就是将新增加的Message按运行时间插入到原有的队列中。然后依据情况调用nativeAwake函数。

    我们跟进一下nativeAwake:

    void NativeMessageQueue::wake() {
        mLooper->wake();
    }
    
    void Looper::wake() {
        uint64_t inc = 1;
        //就是向mWakeEventFd写入数据
        ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
        .............
    }

    在native层的looper初始化时,我们提到过native层的looper将利用epoll来驱动事件,当中构造出的epoll句柄就监听了mWakeEventFd。
    实际上从MessageQueue中取出数据时。若没有数据到来,就会利用epoll进行等待。因此当Java层写入消息时。将会将唤醒处于等待状态的MessageQueue。
    在后文介绍从MessageQueue中提取消息时,将再次分析这个问题。

    1.2 Native层写入消息
    Native层写入消息,依赖于Native层looper的sendMessage函数:

    void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        sendMessageAtTime(now, handler, message);
    }
    
    void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
            const Message& message) {
        size_t i = 0;
        {
            AutoMutex _l(mLock);
    
            //相同须要按时间插入
            size_t messageCount = mMessageEnvelopes.size();
            while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
                i += 1;
            }
    
            //将message包装成一个MessageEnvelope对象
            MessageEnvelope messageEnvelope(uptime, handler, message);
            mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
    
            // Optimization: If the Looper is currently sending a message, then we can skip
            // the call to wake() because the next thing the Looper will do after processing
            // messages is to decide when the next wakeup time should be.  In fact, it does
            // not even matter whether this code is running on the Looper thread.
            if (mSendingMessage) {
                return;
            }
        }
        // Wake the poll loop only when we enqueue a new message at the head.
        if (i == 0) {
            //若插入在队列头部,相同利用wake函数触发epoll唤醒
            wake();
        }
    }

    以上就是向MessageQueue中增加消息的主要流程,接下来我们看看从MessageQueue中取出消息的流程。

    2、提取消息
    当Java层的Looper对象调用loop函数时,就開始使用MessageQueue提取消息了:

    public static void loop() {
        final Looper me = myLooper();
        .......
        for (;;) {
            Message msg = queue.next(); // might block
            .......
            try {
                //调用Message的处理函数进行处理
                msg.target.dispatchMessage(msg);
            }........
        }
    }

    此处我们看看MessageQueue的next函数:

    Message next() {
        //mPtr保存了NativeMessageQueue的指针
        final long ptr = mPtr;
        .......
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
    
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                //会调用Native函数,终于调用IPCThread的talkWithDriver,将数据写入Binder驱动或者读取一次数据
                //不知道在此处进行这个操作的理由?
                Binder.flushPendingCommands();
            }
    
            //处理native层的数据,此处会利用epoll进行blocked
            nativePollOnce(ptr, nextPollTimeoutMillis);
    
            synchronized (this) {
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                //以下事实上就是找出下一个异步处理类型的消息;
                //因为enqueueMessage函数的限制,msg.target不会等于null,正常情况下,以下的代码应该不会运行
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
    
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        //完毕next记录的存储
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        //返回可用的msg
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
    
                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }
    
                //MessageQueue中引入了IdleHandler接口,即当MessageQueue没有数据处理时,调用IdleHandler进行一些工作
    
                //pendingIdleHandlerCount表示待处理的IdleHandler。初始为-1
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    //mIdleHandlers的size默觉得0,调用接口addIdleHandler才干增加
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
    
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }
    
                //将待处理的IdleHandler增加到PendingIdleHandlers中
                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                //调用ArrayList.toArray(T[])节省每次分配的开销;毕竟对于Message.Next这样调用频率较高的函数,能省一点就是一点
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }
    
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler
    
                boolean keep = false;
                try {
                    //运行实现类的queueIdle函数。返回值决定是否继续保留
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }
    
                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }
            pendingIdleHandlerCount = 0;
            nextPollTimeoutMillis = 0;
        }
    }

    整个提取消息的过程,大致上如上图所看到的。
    能够看到在Java层,Looper除了要取出MessageQueue的消息外,还会在队列空暇期运行IdleHandler定义的函数。

    2.1 nativePollOnce
    如今唯一的疑点是nativePollOnce是怎样处理Native层数据的。我们看看相应的native函数:

    static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
            jlong ptr, jint timeoutMillis) {
        //果然Java层调用native层MessageQueue时,将long类型的ptr变为指针
        NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
        nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
    }
    
    void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
        mPollEnv = env;
        mPollObj = pollObj;
        //最后还是进入到Native层looper的pollOnce函数
        mLooper->pollOnce(timeoutMillis);
        mPollObj = NULL;
        mPollEnv = NULL;
    
        if (mExceptionObj) {
            .........
        }
    }

    看看native层looper的pollOnce函数:

    //timeoutMillis为超时等待时间。值为-1时,表示无限等待直到有事件到来。值为0时,表示无需等待
    //outFd此时为null。含义是:存储产生事件的文件句柄
    //outEvents此时为null,含义是:存储outFd上发生了哪些事件,包含可读、可写、错误和中断
    //outData此时为null。含义是:存储上下文数据。事实上调用时传入的參数
    int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
        int result = 0;
        for (;;) {
            //处理response。眼下我们先不关注response的内含
            while (mResponseIndex < mResponses.size()) {
                const Response& response = mResponses.itemAt(mResponseIndex++);
                int ident = response.request.ident;
                if (ident >= 0) {
                    int fd = response.request.fd;
                    int events = response.events;
                    void* data = response.request.data;
    
                    if (outFd != NULL) *outFd = fd;
                    if (outEvents != NULL) *outEvents = events;
                    if (outData != NULL) *outData = data;
                    return ident;
                }
            }
    
            //依据pollInner的结果,进行操作
            if (result != 0) {
                if (outFd != NULL) *outFd = 0;
                if (outEvents != NULL) *outEvents = 0;
                if (outData != NULL) *outData = NULL;
                return result;
            }
    
            //主力还是靠pollInner
            result = pollInner(timeoutMillis);
        }
    }

    跟进一下pollInner函数:

    int Looper::pollInner(int timeoutMillis) {
        // Adjust the timeout based on when the next message is due.
        //timeoutMillis是Java层事件等待事件
        //native层维持了native message的等待时间
        //此处事实上就是选择最小的等待时间
        if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
             int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
             if (messageTimeoutMillis >= 0
                    && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
                timeoutMillis = messageTimeoutMillis;
            }
        }
    
        int result = POLL_WAKE;
        //pollInner初始就清空response
        mResponses.clear();
        mResponseIndex = 0;
    
        // We are about to idle.
        mPolling = true;
    
        //利用epoll等待mEpollFd监控的句柄上事件到达
        struct epoll_event eventItems[EPOLL_MAX_EVENTS];
        int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    
        // No longer idling.
        mPolling = false;
    
        // Acquire lock.
        mLock.lock();
    
        //又一次调用rebuildEpollLocked时,将使得epoll句柄能够监听新增加request相应的fd
        if (mEpollRebuildRequired) {
            mEpollRebuildRequired = false;
            rebuildEpollLocked();
            goto Done;
        }
    
        // Check for poll error.
        if (eventCount < 0) {
            if (errno == EINTR) {
                goto Done;
            }
            ......
            result = POLL_ERROR;
            goto Done;
        }
    
        // Check for poll timeout.
        if (eventCount == 0) {
            result = POLL_TIMEOUT;
            goto Done;
        }
    
        for (int i = 0; i < eventCount; i++) {
            if (fd == mWakeEventFd) {
                if (epollEvents & EPOLLIN) {
                    //前面已经分析过,当java层或native层有数据写入队列时,将写mWakeEventFd,以触发epoll唤醒
                    //awoken将读取并清空mWakeEventFd上的数据
                    awoken();
                } else {
                    .........
                }
            } else {
                //epoll相同监听的request相应的fd
                ssize_t requestIndex = mRequests.indexOfKey(fd);
                if (requestIndex >= 0) {
                    int events = 0;
                    if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
                    if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
                    if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
                    if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
                    //存储这个fd相应的response
                    pushResponse(events, mRequests.valueAt(requestIndex));
                } else {
                    ..........
                }
            }
        }
    
    Done:
        // Invoke pending message callbacks.
        mNextMessageUptime = LLONG_MAX;
        //处理Native层的Message
        while (mMessageEnvelopes.size() != 0) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
            if (messageEnvelope.uptime <= now) {
                // Remove the envelope from the list.
                // We keep a strong reference to the handler until the call to handleMessage
                // finishes.  Then we drop it so that the handler can be deleted *before*
                // we reacquire our lock.
                {
                    sp<MessageHandler> handler = messageEnvelope.handler;
                    Message message = messageEnvelope.message;
                    mMessageEnvelopes.removeAt(0);
                    mSendingMessage = true;
                    mLock.unlock();
    
                    //处理Native Message
                    handler->handleMessage(message);
                }
                mLock.lock();
                mSendingMessage = false;
                result = POLL_CALLBACK;
            } else {
                // The last message left at the head of the queue determines the next wakeup time.
                mNextMessageUptime = messageEnvelope.uptime;
                break;
            }
        }
    
        // Release lock.
        mLock.unlock();
    
        //处理带回调函数的response
        for (size_t i = 0; i < mResponses.size(); i++) {
            Response& response = mResponses.editItemAt(i);
            if (response.request.ident == POLL_CALLBACK) {
                int fd = response.request.fd;
                int events = response.events;
                void* data = response.request.data;
    
                //调用response的callback
                int callbackResult = response.request.callback->handleEvent(fd, events, data);
                if (callbackResult == 0) {
                    removeFd(fd, response.request.seq);
                }
    
                response.request.callback.clear();
                result = POLL_CALLBACK;
            }
        }
        return result;
    }

    说实话native层的代码写的非常乱,该函数的功能比較多。


    如上图所看到的。在nativePollOnce中利用epoll监听是否有数据到来。然后处理native message、native response。

    最后,我们看看怎样在native层中增加request。

    3 增加监控请求
    native层增加request依赖于looper的接口addFd:

    //fd表示须要监听的句柄
    //ident的含义还没有搞明确
    //events表示须要监听的事件,比如EVENT_INPUT、EVENT_OUTPUT、EVENT_ERROR和EVENT_HANGUP中的一个或多个
    //callback为事件发生后的回调函数
    //data为回调函数相应的參数
    int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
        return addFd(fd, ident, events, callback ?

    new SimpleLooperCallback(callback) : NULL, data); }

    结合上文native层轮询队列的操作,我们大致能够知道:addFd的目的,就是让native层的looper监控新增加的fd上是否有指定事件发生。
    假设发生了指定的事件,就利用回调函数及參数构造相应的response。


    native层的looper处理response时,就能够运行相应的回调函数了。

    看看实际的代码:

    int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
        ........
        {
            AutoMutex _l(mLock);
    
            //利用參数构造一个request
            Request request;
            request.fd = fd;
            request.ident = ident;
            request.events = events;
            request.seq = mNextRequestSeq++;
            request.callback = callback;
            request.data = data;
            if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
    
            struct epoll_event eventItem;
            request.initEventItem(&eventItem);
    
            //推断之前是否已经利用该fd构造过Request
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex < 0) {
                //mEpollFd新增一个需监听fd
                int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
                .......
                mRequests.add(fd, request);
            } else {
                //mEpollFd改动旧的fd相应的监听事件
                int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
                if (epollResult < 0) {
                    if (errno == ENOENT) {
                        // Tolerate ENOENT because it means that an older file descriptor was
                        // closed before its callback was unregistered and meanwhile a new
                        // file descriptor with the same number has been created and is now
                        // being registered for the first time. 
                        epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
                        .......
                    }
                    //错误发生又一次增加时。安排EpollRebuildLocked。将让epollFd又一次增加一次待监听的fd
                    scheduleEpollRebuildLocked();
                }
                mRequests.replaceValueAt(requestIndex, request);
            }
        }
    }

    对增加监控请求的处理。在上文介绍pollInner函数时已做分析。此处不再赘述。

    三、总结

    1、流程总结

    MessageQueue的整个流程包含了Java部分和Native部分,从图中能够看出Native层的比重还是非常大的。

    我们结合上图回顾一下整个MessageQueue相应的处理流程:
    1、Java层创建Looper对象时,将会创建Java层的MessageQueue;Java层的MessageQueue初始化时。将利用Native函数创建出Native层的MessageQueue。

    2、Native层的MessageQueue初始化后,将创建相应的Native Looper对象。Native对象初始化时。将创建相应epollFd和WakeEventFd。当中,epollFd将作为epoll的监听句柄。初始时epollFd仅监听WakeEventFd。

    3、图中红色线条为Looper从MessageQueue中取消息时。处理逻辑的流向。


    3.1、当Java层的Looper開始循环时,首先须要通过JNI函数调用Native Looper进行pollOnce的操作。

    3.2、Native Looper開始运行后,须要等待epollFd被唤醒。当epollFd等待超时或监听的句柄有事件到来。Native Looper就能够開始处理事件了。

    3.3、在Native层,Native Looper将先处理Native MessageQueue中的消息,再调用Response相应的回调函数。

    3.4、本次循环中。Native层事件处理完毕后。才開始处理Java层中MessageQueue的消息。若MessageQueue中没有消息须要处理,而且MessageQueue中存在IdleHandler时。将调用IdleHandler定义的处理函数。

    图中蓝色部分为相应的函数调用:
    在Java层:
    利用MessageQueue的addIdleHandler,能够为MessageQueue增加IdleHandler;
    利用MessageQueue的enqueueMessage,能够向MessageQueue增加消息;必要时将利用Native函数向Native层的WakeEventFd写入消息,以唤醒epollFd。

    在Native层:
    利用looper:sendMessage。能够为Native MessageQueue增加消息;相同。要时将向Native层的WakeEventFd写入消息。以唤醒epollFd。
    利用looper:addFd,能够向Native Looper注冊监听请求。监听请求包含需监听的fd、监听的事件及相应的回调函数等,监听请求相应的fd将被成为epollFd监听的对象。

    当被监听的fd发生相应的事件后,将会唤醒epollFd。此时将生成相应response增加的response List中,等待处理。一旦response被处理,就会调用相应的回调函数。

    2、注意事项
    MessageQueue在Java层和Native层有各自的存储结构。能够分别增加消息。从处理逻辑来看。会优先处理native层的Message。然后处理Native层生成的response,最后才是处理Java层的Message。

  • 相关阅读:
    PrefixSpan序列模式挖掘算法
    PrefixSpan序列模式挖掘算法
    CBA算法---基于关联规则进行分类的算法
    CBA算法---基于关联规则进行分类的算法
    CBA算法---基于关联规则进行分类的算法
    RoughSets属性约简算法
    RoughSets属性约简算法
    hdu Proud Merchants
    hdu I NEED A OFFER!
    hdu Watch The Movie
  • 原文地址:https://www.cnblogs.com/llguanli/p/8743292.html
Copyright © 2011-2022 走看看