主頁 > 移動端開發 > Handler ,MessageQueue 的Looper中epoll監聽的fd

Handler ,MessageQueue 的Looper中epoll監聽的fd

2021-12-31 09:32:40 移動端開發

hi,同學們大家好!
這些天有學員再群里問起了Handler中有個資料監聽相關問題,學員有的認為Handler資料傳遞是靠流傳遞,誤認為是epoll中監聽的fd進行傳遞的,這個其實有必要更正這個學員的一個觀點:
1、handler的資料傳遞完全是在自己行程中,所以完全不需要什么fd的流來傳遞,就相當于一個全域變數一樣,你需要通過什么socket什么來傳遞資料么,你直接記憶體變數就可以訪問到
2、那么學員就有疑問,那么handler looper說是基于epoll檢測fd方式,epoll只是來監聽回呼通知作用,那么它監聽的fd到底是個什么東西,如果不是流傳遞
這里我們就來揭開handler中looper的epoll監聽的fd到底是什么型別的:
其實在我們android跨行程通訊實戰課程中原來也講解過Looper,其實Looper在java層就是一個簡單的包裝,真正干活在Loop.cpp中,而且這個Looper.cpp不在framework路徑下面,
其實實在system/core路徑下面:

test@test-Lenovo:~/xiaomi5/system/core$ find -name Loop*
./libutils/Looper.cpp
./libutils/Looper_test.cpp
./libutils/include/utils/Looper.h

下面我們從Loop.java開始一步步追:

    public static void loop() {
        //省略部分
        for (;;) {
            Message msg = queue.next(); // might block
           //省略部分
        }
    }

可以看出loop是一個死回圈在呼叫queue.next(),這樣來一直源源不斷取訊息:
來看看queue.next():

frameworks/base/core/java/android/os/MessageQueue.java

Message next() {
   //省略部分
        for (;;) {

            nativePollOnce(ptr, nextPollTimeoutMillis);
  //省略部分
        }
    }

這里呼叫是nativePollOnce,是一個native方法,即到達了native,來看看nativePollOnce方法:
frameworks/base/core/jni/android_os_MessageQueue.cpp

static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jlong ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}

這里呼叫是NativeMessageQueue的pollOnce,NativeMessageQueue本身也在android_os_MessageQueue類中,這里來看一下:

void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
    mPollEnv = env;
    mPollObj = pollObj;
    mLooper->pollOnce(timeoutMillis);
    mPollObj = NULL;
    mPollEnv = NULL;

    if (mExceptionObj) {
        env->Throw(mExceptionObj);
        env->DeleteLocalRef(mExceptionObj);
        mExceptionObj = NULL;
    }
}

這里大家看一下呼叫了是 mLooper->pollOnce(timeoutMillis),看到了開頭說的Loop.cpp,它是在system/core/libutils目錄:
system/core/libutils/include/utils/Looper.h

    int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
    inline int pollOnce(int timeoutMillis) {
        return pollOnce(timeoutMillis, nullptr, nullptr, nullptr);
    }

這里呼叫是int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData)方法:

nt Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        //省略

        result = pollInner(timeoutMillis);
    }
}

這里又呼叫了pollInner:

int Looper::pollInner(int timeoutMillis) {
//省略部分
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
//省略部分
    return result;
}

這里大家是不是看到一個非常非常熟悉的epoll_wait,即它就是沒有訊息時候阻塞,有訊息時候喚醒的核心,也是handler是epoll的關鍵體現就是它,那么問題是它到達監聽是哪個fd的變化呢?

其實本質上喚醒的fd是mWakeEventFd,而這個又是由誰進行賦值呢?只要找到他的賦值就可以看出他是個什么樣的fd:

Looper::Looper(bool allowNonCallbacks)
    : mAllowNonCallbacks(allowNonCallbacks),
      mSendingMessage(false),
      mPolling(false),
      mEpollRebuildRequired(false),
      mNextRequestSeq(0),
      mResponseIndex(0),
      mNextMessageUptime(LLONG_MAX) {
    mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));//這里就是對mWakeEventFd進行賦值
    LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0, "Could not make wake event fd: %s", strerror(errno));

    AutoMutex _l(mLock);
    rebuildEpollLocked();
}


可以看出mWakeEventFd本質是通過eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC),那么eventfd又是個什么呢?
這里我們Ubuntu使用man來看看它是什么:

VENTFD(2)                                                                            Linux Programmer's Manual                                                                            EVENTFD(2)

NAME
       eventfd - create a file descriptor for event notification

SYNOPSIS
       #include <sys/eventfd.h>

       int eventfd(unsigned int initval, int flags);

DESCRIPTION
       eventfd()  creates  an "eventfd object" that can be used as an event wait/notify mechanism by user-space applications, and by the kernel to notify user-space applications of events.  The ob‐
       ject contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the kernel.  This counter is initialized with the value specified in the argument initval.

       As its return value, eventfd() returns a new file descriptor that can be used to refer to the eventfd object.

       The following values may be bitwise ORed in flags to change the behavior of eventfd():

       EFD_CLOEXEC (since Linux 2.6.27)
              Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor.  See the description of the O_CLOEXEC flag in open(2) for reasons why this may be useful.

       EFD_NONBLOCK (since Linux 2.6.27)
              Set the O_NONBLOCK file status flag on the open file description (see open(2)) referred to by the new file descriptor.  Using this flag saves extra calls to fcntl(2)  to  achieve  the
              same result.

       EFD_SEMAPHORE (since Linux 2.6.30)
              Provide semaphore-like semantics for reads from the new file descriptor.  See below.

       In Linux up to version 2.6.26, the flags argument is unused, and must be specified as zero.

       The following operations can be performed on the file descriptor returned by eventfd():

       read(2)
              Each successful read(2) returns an 8-byte integer.  A read(2) fails with the error EINVAL if the size of the supplied buffer is less than 8 bytes.

              The value returned by read(2) is in host byte order—that is, the native byte order for integers on the host machine.

              The  semantics  of read(2) depend on whether the eventfd counter currently has a nonzero value and whether the EFD_SEMAPHORE flag was specified when creating the eventfd file descrip‐
              tor:

              *  If EFD_SEMAPHORE was not specified and the eventfd counter has a nonzero value, then a read(2) returns 8 bytes containing that value, and the counter's value is reset to zero.

              *  If EFD_SEMAPHORE was specified and the eventfd counter has a nonzero value, then a read(2) returns 8 bytes containing the value 1, and the counter's value is decremented by 1.

              *  If the eventfd counter is zero at the time of the call to read(2), then the call either blocks until the counter becomes nonzero (at which time, the read(2) proceeds  as  described
                 above) or fails with the error EAGAIN if the file descriptor has been made nonblocking.

       write(2)
              A  write(2) call adds the 8-byte integer value supplied in its buffer to the counter.  The maximum value that may be stored in the counter is the largest unsigned 64-bit value minus 1
              (i.e., 0xfffffffffffffffe).  If the addition would cause the counter's value to exceed the maximum, then the write(2) either blocks until a read(2) is performed on the  file  descrip‐
              tor, or fails with the error EAGAIN if the file descriptor has been made nonblocking.

              A write(2) fails with the error EINVAL if the size of the supplied buffer is less than 8 bytes, or if an attempt is made to write the value 0xffffffffffffffff.

大致就是說:

eventfd - create a file descriptor for event notification

即專門用來創建事件通知檔案描述符fd的一個方法,即他僅僅作用就是通知事件這種,不是平常見到的socket fd那種
好了到這里基本上解密了handler的fd到底是什么fd,它既不是 大家想的那種socket流fd,管道流fd,就是linux上專門系統方法evnetfd創建的事件通知fd

如果需要學習更多framework只是和視頻可以b站關注:千里馬學框架,購買課程最好加入422901085群里找千里馬要優惠和答疑

課程答疑和新課資訊:QQ交流群:422901085進行課程討論,加群主qq享受 優惠
FrameWork入門課視頻鏈接:https://edu.csdn.net/course/detail/30298
FrameWork實戰課1視頻鏈接:https://edu.csdn.net/course/detail/30275
FrameWork跨行程通信視頻鏈接:https://edu.csdn.net/course/detail/35911
專題博客系列:
Android 8.1 zygote 啟動程序原始碼
Android Framework實戰視頻–Zygote的fork行程篇
Android Framework實戰視頻–SystemServer啟動篇
Android Framework實戰視頻–SystemServer啟動FallbackHome篇
Android Framework實戰視頻–FallbackHome行程啟動及Activity啟動篇
Android Framework實戰視頻–FallbackHome結束啟動Launcher篇
Android Framework實戰視頻–BootAnimation的啟動原始碼分析(Android8.1)

Android Framework實戰視頻–init行程的bootanimation啟動原始碼分析(補充Android 10部分的BootAnimation的啟動原始碼分析)

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/398708.html

標籤:其他

上一篇:css 實作最后一行兩側對齊,考慮ios text-align-last 不支持iOS

下一篇:Android 進階——系統啟動之SystemServer創建并啟動Installer服務(八)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more