Android Binder為什么只需要一次拷貝?

      網友投稿 1294 2025-04-01

      Binder是Android特有的一種IPC(進程間通信)方式。


      IPC機制是從Unix系統發展而來的,它只能提供原始進程間通信手段,通信雙方需要處理線程同步、內存管理等問題。

      傳統的IPC方式有:Socket、匿名管道(Pipe),命名管道(FIFO),信號量(Semaphore),消息隊列。Android系統只保留了Socket、匿名管道(Pipe)兩種。

      Binder的IPC機制融合了RPC(遠程過程調用)概念,它是一種面向對象的遠程調用。

      Android系統使用了Linux內核。Linux中的進程是被隔離開,不能直接通信的。Android的應用程序也是Linux的進程,因此它也是被隔離開,不能直接通信的。

      Linux中的進程是如何通信的,了解這一點可以為我們了解Binder的IPC通信作個鋪墊。

      在Linux的用戶空間中的進程都是被隔離開的,使得進程之間不能共享數據,不能互相訪問,彼此獨立。這也是出于進程安全的考慮才這樣做。也因此有了IPC(進程間通信)的機制,提供一種安全的手段使用進程間能夠互相通信。這與內核空間不一樣,內核空間的進程是可以直接互相訪問,直接通信的。

      用戶空間的進程要訪問內核空間需要通過系統調用。內核空間的代碼都是linux內核的代碼和數據。這些代碼都是有權限直接操作周圍的硬件。用戶空間要使用這些硬件都只能通過linux內核來完成,一來簡化了用戶空間程序的編寫,二來保證了系統的安全。

      內核在創建進程的時候會創建進程控制塊以及進程的堆棧。每個進程都有兩個棧:用戶棧、內核棧。用戶棧在用戶空間中,內核棧在內核空間中。

      用戶棧用于保存用戶進程的子程序間相互調用的參數、返回值以及局部變量等信息。

      在談到內核棧前,要先說說系統調用。系統調用的實質是通過指令產生中斷(軟中斷)。由于系統調用或其他中斷,進程會從用戶態轉換為內核態時,意味著將要執行內核中的代碼,那么進程所使用的棧就不能再是用戶棧了,而要使用內核中的棧。實際上,進程在進入內核態之后,會把用戶態的堆棧地址保存在內核態堆棧中,然后設置堆棧寄存器地址為內核棧地址,這樣就從用戶棧轉換成內核棧。

      當內核中的代碼執行完后,進程就要回到它的用戶空間,所以進程從內核態轉換回用戶態時,會將堆棧寄存器的地址再重新設置成用戶態的堆棧地址,這就是所謂的現場恢復。

      在linux中,內核在創建進程時,會給進程分配task_struct結構體,同時分配兩塊連續的物理空間,一塊供堆棧使用,另一塊則保存進程描述符task_struct,這個整體就叫做進程的內核棧。

      每當進程從用戶態切換到內核態時,內核棧總是空的。當進程在用戶態執行時,使用的是用戶棧,切換到內核態運行時,內核棧保存進程在內核中運行的相關信息。重回到用戶態時,內核棧中保存的信息全部恢復,因此,進程從內核態切換到用戶態時,內核棧總是空的。用戶態切換到內核棧時,正因為內核棧是空的,所以只需將棧寄存器值設置成內核棧棧頂指針即可。

      通過上面的介紹,我們對Linux的內核有了更多的了解,現在來聊聊Linux進程間的通信。在Linux進程之間要交換數據必須通過內核,首在內核中開辟一塊緩沖區,進程A把數據從用戶空間拷到內核緩沖區,進程B再從內核緩沖區把數據讀走。

      從用戶空間拷數據到內核空間可以用copy_from_user()或get_user()。

      從內核空間向用戶空間拷數據可以用copy_to_user()或put_user()。

      這就是所謂的兩次拷貝了。

      Binder一次拷貝將用到Linux內存映射的技術。我們先來了解內存映射,再來看Binder的一次拷貝。

      mmap()這個就是內存映射的系統調用函數。它可以將一個文件、一段物理內存,甚至內核空間映射到進程的虛擬內存地址(這個虛擬內存地址可以這么理解,我們寫的程序的邏輯地址都從0開始,可以一直往后延伸。平時我們寫代碼不用考慮這個,但是我們的電腦在運行就不得不考慮這個了,這個虛擬地址可以通過某種方式,如地址轉換器,計算出真實的物理地址。但是對程序員而言只管邏輯地址即可。)。有了這種映射關系后,就可以直接完成對這個文件或這段內存直接讀寫了。

      我們經常聽說Binder驅動。那些什么是驅動,Binder驅動有什么特別之外?首先,驅動是一種用于實現對硬件進行相關操作的程序,驅動可以為上層應用屏蔽掉硬件特性。一般,驅動都是操作相關的硬件的。但是Binder驅動并沒有相關硬件與之對應,所以我們說Binder驅動虛擬的字符設備(Linux驅動有三大類:字符設備驅動、塊設備驅動、網絡設備驅動),它注冊在/dev/binder中。Binder驅動定義了一套Binder通信協議,用于負責建立進程間的Binder通信,提供了數據包在進程之間傳遞的支持。

      由于Binder驅動不是Linux原有的,而是Android特有的,因此想Linux內核支持Binder驅動,就要把Binder驅動動態加載到Linux內核中來運行。因此Binder驅動就只能做成一個模塊,然后利用Linux可加載內核模塊(Loadable Kernal Module)機制動態加載Binder驅動,使其在內核中與內核一起運行。既然Binder驅動運行在內核了,那么用戶空間的程序對其調用也必須通過系統調用來完成。

      Android Binder為什么只需要一次拷貝?

      在我們了解Binder具體是如何完成數據包在進程間的傳遞之前,讓我們來熟悉一下Linux的IPC是如何工作?因為Binder IPC的出現也不是一下就完成的:

      通常Linux 的IPC通信,首先會將消息發送方將要發送的數據放在內存的緩存區中;

      然后調用系統調用進入內核態,Linux為發送方進程在內核空間開避一塊內核緩存區(分配內核空間);

      緊接著調用copy_from_user()將數據從用戶空間的內存緩存區拷貝到內核空間的內核緩存區中。

      對于接收方而言:

      接收方首先在接收數據前,在自己的用戶空間開辟一塊內存緩存區,用于接收數據;

      然后Linux為接收方進程在內核空間中調用copy_to_user()將數據從內核緩存區拷貝到接收方進程的用戶空間的內存緩存區。這樣就完成了一次進程間的通信。

      所以傳統的Linux IPC有兩次拷貝。這些拷由都需要用到系統調用,開銷會比較大。Binder是如何實現一次拷貝,將這種開銷降低的?

      Binder IPC

      有了前面的知識做鋪墊,在這個時候來介紹Binder IPC是合適的。

      Binder服務端進程在啟動后,通過系統調用調用Binder驅動(其運行在內核空間)在內核空間創建一個數據接收緩存區(通過調用binder_open來完成),緊接著再通過系統調用調用binder_mmap()建立映射。具體過程是首先申請一塊物理內存,然后建立Binder服務端的用戶空間與內核空間一塊區域的映射關系, 這個映射關系就記錄在申請的這一塊物理內存中。依靠這個建立起來的映射,用戶空間與內核空間創建的數據接收緩存區之間就建立了映射關系。

      當Client向Binder服務端發送通信請求時,這個請求數據打包好后通過系統調用先到Binder驅動,再由Binder驅動調用copy_from_user()將數據從client的用戶空間拷貝到內核空間的數據接收緩存區中。因為內核空間的數據接收緩存區與接收進程用戶空間的內存存在映射,因此也就相當于把數據發送到了接收方進程的用戶空間,從而減少了一次拷貝。

      整個過程只有一次拷貝。這種一次拷貝帶來的效率是明顯的,為什么呢?因為首先它減少了數據的拷貝次數,用存讀寫取代了I/O讀寫,提高了文件讀取效率。

      你明白了嗎?

      Android Linux 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:怎么刪除頁數??(電腦上pdf怎么刪除頁數)
      下一篇:WPS文字插入單選按鈕和復選框的方法介紹(圖文)
      相關文章
      亚洲av无码国产精品夜色午夜| 国产性爱在线观看亚洲黄色一级片 | 久久久久噜噜噜亚洲熟女综合 | 国产亚洲精品久久久久秋霞 | 亚洲国产模特在线播放| 亚洲精品视频在线免费| 亚洲视频精品在线| 亚洲人成网站在线播放影院在线 | 亚洲av永久无码精品秋霞电影秋| 国产精品亚洲专区在线观看| 亚洲成AV人综合在线观看| 亚洲无成人网77777| 亚洲一级毛片中文字幕| 中文字幕亚洲男人的天堂网络| 亚洲av专区无码观看精品天堂| 亚洲1区1区3区4区产品乱码芒果 | 激情综合亚洲色婷婷五月APP| 亚洲自国产拍揄拍| 久久久久亚洲国产| 亚洲AV无码国产一区二区三区| 国产AV无码专区亚洲AV蜜芽| 日韩亚洲人成网站| 亚洲毛片不卡av在线播放一区 | 亚洲午夜久久久精品电影院| 亚洲AV无码成人专区| 中文无码亚洲精品字幕| 亚洲人成色777777老人头| 亚洲乱色伦图片区小说| 在线观看亚洲免费| 亚洲成a人无码av波多野按摩| 亚洲精品综合久久| 亚洲国产精品成人久久蜜臀| 久久久久亚洲AV成人网| 国产A在亚洲线播放| 老司机亚洲精品影院| 亚洲国产精品乱码在线观看97| 亚洲综合综合在线| 亚洲依依成人亚洲社区| 亚洲AⅤ永久无码精品AA| 亚洲一区二区三区AV无码| 亚洲av丰满熟妇在线播放|