日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析

發(fā)布時間:2023/12/6 Android 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?在前面一篇文章Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)驅(qū)動程序源代碼分析中,我們系統(tǒng)地介紹了Android系統(tǒng)匿名共享內(nèi)存的實現(xiàn)原理,其中著重介紹了它是如何輔助內(nèi)存管理系統(tǒng)來有效地管理內(nèi)存的,在再前面一篇文章Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃中,我們還提到,Android系統(tǒng)匿名共享內(nèi)存的另外一特點是通過Binder進程間通信機制來實現(xiàn)進程間共享的,本文中,將詳細介紹Android系統(tǒng)匿名共享內(nèi)存是如何使用Binder進程間通信機制來實現(xiàn)進程間共享的。

?? ? ? ?由于Android系統(tǒng)匿名共享內(nèi)存在進程間共享的原理涉及到Binder進程間通信機制的相關知識,所以希望讀者在繼續(xù)閱讀本文之前,最好對Android系統(tǒng)的Binder進程間通信機制有一定的了解,具體可以參考Android進程間通信(IPC)機制Binder簡要介紹和學習計劃這篇文章。

?? ? ? ?在Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃這篇文章中,我們舉了一個例子來簡要地介紹了Android系統(tǒng)的匿名共享內(nèi)存機制及其使用方法,在這篇文章中,我們繼續(xù)以這個實例來說明Android系統(tǒng)的匿名共享內(nèi)存是如何使用Binder進程間通信機制來實現(xiàn)進程間共享的。為了方便描述,結(jié)合前面的Binder進程間通信機制知識,我們通過下面這個序列圖來總結(jié)這個實例中的匿名共享內(nèi)存文件的文件描述符在進程間傳輸?shù)倪^程:

?? ? ? ?這里, 我們需要關注的便是虛線框部分了,它在Binder驅(qū)動程序中實現(xiàn)了在兩個進程中共享同一個打開文件的方法。我們知道,在Linux系統(tǒng)中,文件描述符其實就是一個整數(shù)。每一個進程在內(nèi)核空間都有一個打開文件的數(shù)組,這個文件描述符的整數(shù)值就是用來索引這個數(shù)組的,而且,這個文件描述符只是在本進程內(nèi)有效,也就是說,在不同的進程中,相同的文件描述符的值,代表的可能是不同的打開文件。因此,在進程間傳輸文件描述符時,不能簡要地把一個文件描述符從一個進程傳給另外一個進程,中間必須做一過轉(zhuǎn)換,使得這個文件描述在目標進程中是有效的,并且它和源進程的文件描述符所對應的打開文件是一致的,這樣才能保證共享。

?? ? ? ?在淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路一文中,我們介紹了用來傳輸?shù)腂inder對象的數(shù)據(jù)結(jié)構(gòu)struct flat_binder_object,它定義在kernel/common/drivers/staging/android/binder.h 文件中:

  • /* ?
  • ?*?This?is?the?flattened?representation?of?a?Binder?object?for?transfer ?
  • ?*?between?processes.??The?'offsets'?supplied?as?part?of?a?binder?transaction?
  • ?*?contains?offsets?into?the?data?where?these?structures?occur.??The?Binder ?
  • ?*?driver?takes?care?of?re-writing?the?structure?type?and?data?as?it?moves ?
  • ?*?between?processes. ?
  • ?*/ ?
  • struct?flat_binder_object?{ ?
  • ????/*?8?bytes?for?large_flat_header.?*/ ?
  • ????unsigned?long???????type; ?
  • ????unsigned?long???????flags; ?
  • ?
  • ????/*?8?bytes?of?data.?*/ ?
  • ????union?{ ?
  • ????????void????????*binder;????/*?local?object?*/ ?
  • ????????signed?long?handle;?????/*?remote?object?*/ ?
  • ????}; ?
  • ?
  • ????/*?extra?data?associated?with?local?object?*/ ?
  • ????void????????????*cookie; ?
  • };?
  • ???????域type是一個枚舉類型,它的取值范圍是:

  • enum?{ ?
  • ????BINDER_TYPE_BINDER??=?B_PACK_CHARS('s',?'b',?'*',?B_TYPE_LARGE), ?
  • ????BINDER_TYPE_WEAK_BINDER?=?B_PACK_CHARS('w',?'b',?'*',?B_TYPE_LARGE), ?
  • ????BINDER_TYPE_HANDLE??=?B_PACK_CHARS('s',?'h',?'*',?B_TYPE_LARGE), ?
  • ????BINDER_TYPE_WEAK_HANDLE?=?B_PACK_CHARS('w',?'h',?'*',?B_TYPE_LARGE), ?
  • ????BINDER_TYPE_FD??????=?B_PACK_CHARS('f',?'d',?'*',?B_TYPE_LARGE), ?
  • };?
  • ?? ? ? ?這里我們要介紹的Binder對象的type便是BINDER_TYPE_FD了,要傳輸?shù)奈募枋龇闹当4嬖趆andle域中。

    ?

    ?? ? ? ?在Android系統(tǒng)進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文中,我們詳細介紹了Binder對象在進程間通信傳輸?shù)耐暾^程,這里就不再詳述了,有興趣的讀都可以回過頭去參考一下。這里,我們只關注文件描述符類型的Binder對象在Binder驅(qū)動程序中的相關處理邏輯。

    ?? ? ? ?文件描述符類型的Binder對象在Binder驅(qū)動程序中的相關處理邏輯實現(xiàn)在binder_transact函數(shù),這個函數(shù)定義在kernel/common/drivers/staging/android/binder.c文件中:

  • static?void ?
  • binder_transaction(struct?binder_proc?*proc,?struct?binder_thread?*thread, ?
  • struct?binder_transaction_data?*tr,?int?reply) ?
  • { ?
  • ????struct?binder_transaction?*t; ?
  • ????struct?binder_work?*tcomplete; ?
  • ????size_t?*offp,?*off_end; ?
  • ????struct?binder_proc?*target_proc; ?
  • ????struct?binder_thread?*target_thread?=?NULL; ?
  • ????struct?binder_node?*target_node?=?NULL; ?
  • ????struct?list_head?*target_list; ?
  • ????wait_queue_head_t?*target_wait; ?
  • ????struct?binder_transaction?*in_reply_to?=?NULL; ?
  • ????struct?binder_transaction_log_entry?*e; ?
  • ????uint32_t?return_error; ?
  • ?
  • ????...... ?
  • ???? ?
  • ?
  • ????offp?=?(size_t?*)(t->buffer->data?+?ALIGN(tr->data_size,?sizeof(void?*))); ?
  • ?
  • ????...... ?
  • ?
  • ????off_end?=?(void?*)offp?+?tr->offsets_size; ?
  • ????for?(;?offp?<?off_end;?offp++)?{ ?
  • ????????struct?flat_binder_object?*fp; ?
  • ????????...... ?
  • ????????fp?=?(struct?flat_binder_object?*)(t->buffer->data?+?*offp); ?
  • ????????switch?(fp->type)?{ ?
  • ????????...... ?
  • ????????case?BINDER_TYPE_FD:?{ ?
  • ????????????int?target_fd; ?
  • ????????????struct?file?*file; ?
  • ?
  • ????????????if?(reply)?{ ?
  • ????????????????if?(!(in_reply_to->flags?&?TF_ACCEPT_FDS))?{ ?
  • ????????????????????binder_user_error("binder:?%d:%d?got?reply?with?fd,?%ld,?but?target?does?not?allow?fds\n", ?
  • ????????????????????????????????????proc->pid,?thread->pid,?fp->handle); ?
  • ????????????????????return_error?=?BR_FAILED_REPLY; ?
  • ????????????????????goto?err_fd_not_allowed; ?
  • ????????????????} ?
  • ????????????}?else?if?(!target_node->accept_fds)?{ ?
  • ????????????????binder_user_error("binder:?%d:%d?got?transaction?with?fd,?%ld,?but?target?does?not?allow?fds\n", ?
  • ????????????????????????????????proc->pid,?thread->pid,?fp->handle); ?
  • ????????????????return_error?=?BR_FAILED_REPLY; ?
  • ????????????????goto?err_fd_not_allowed; ?
  • ????????????} ?
  • ?
  • ????????????file?=?fget(fp->handle); ?
  • ????????????if?(file?==?NULL)?{ ?
  • ????????????????binder_user_error("binder:?%d:%d?got?transaction?with?invalid?fd,?%ld\n", ?
  • ????????????????????????????????????proc->pid,?thread->pid,?fp->handle); ?
  • ????????????????return_error?=?BR_FAILED_REPLY; ?
  • ????????????????goto?err_fget_failed; ?
  • ????????????} ?
  • ????????????target_fd?=?task_get_unused_fd_flags(target_proc,?O_CLOEXEC); ?
  • ????????????if?(target_fd?<?0)?{ ?
  • ????????????????fput(file); ?
  • ????????????????return_error?=?BR_FAILED_REPLY; ?
  • ????????????????goto?err_get_unused_fd_failed; ?
  • ????????????} ?
  • ????????????task_fd_install(target_proc,?target_fd,?file); ?
  • ????????????if?(binder_debug_mask?&?BINDER_DEBUG_TRANSACTION) ?
  • ????????????????????printk(KERN_INFO?"????????fd?%ld?->?%d\n",?fp->handle,?target_fd); ?
  • ????????????/*?TODO:?fput??*/ ?
  • ????????????fp->handle?=?target_fd; ?
  • ????????}?break; ?
  • ?
  • ????????...... ?
  • ????????} ?
  • ????} ?
  • ???? ?
  • ????...... ?
  • ?
  • }?
  • ?? ? ? ?這里,我們先明確一下在Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃這篇文章中所舉的例子獲取匿名共享內(nèi)存文件的文件描述符的場景。匿名共享內(nèi)存文件是在Server進程創(chuàng)建的,Client通過IMemoryService.getFileDescriptor去獲取Server進程所創(chuàng)建的匿名共享內(nèi)存文件的文件描述符,Server進程在返回這個文件描述符的過程中進入到Binder驅(qū)動程序,即這里的binder_transact函數(shù)。因此,這里的當前執(zhí)行binder_transact函數(shù)的進程是Server進程,即源進程是Server進程,而目標進程是Client進程,就是這里的target_proc所表示的進程了。

    ?

    ?? ? ? ?函數(shù)binder_transaction處理文件描述符類型的Binder對象就在中間的for循環(huán)里面。

    ?? ? ? 首先是獲得Binder對象,并保存在本地變量fp中:

  • fp?=?(struct?flat_binder_object?*)(t->buffer->data?+?*offp);?
  • ?????? 文件描述符的值就保存在fp->handle中,通過fget函數(shù)取回這個文件描述符所對應的打開文件結(jié)構(gòu):

  • file?=?fget(fp->handle);?
  • ? ? ? 這里的file是一個struct file指針,它表示一個打開文件結(jié)構(gòu)。注間,在Linux系統(tǒng)中,打開文件結(jié)構(gòu)struct file是可以在進程間共享的,它與文件描述符不一樣。

    ?

    ?? ? ? 接著在目標進程中獲得一個空閑的文件描述符:

  • target_fd?=?task_get_unused_fd_flags(target_proc,?O_CLOEXEC);?
  • ?? ? ? 現(xiàn)在,在目標進程中,打開文件結(jié)構(gòu)有了,文件描述符也有了,接下來就可以把這個文件描述符和這個打開文件結(jié)構(gòu)關聯(lián)起來就可以了:

  • task_fd_install(target_proc,?target_fd,?file);?
  • ?????? 由于這個Binder對象最終是要返回給目標進程的,所以還要修改fp->handle的值,它原來表示的是在源進程中的文件描述符,現(xiàn)在要改成目標進程的文件描述符:

  • fp->handle?=?target_fd;?
  • ?? ? ?

    ?? ? ? 這樣,對文件描述符類型的Binder對象的處理就完成了。目標進程拿到這個文件描述符后,就可以和源進程一起共享打開文件了。

    ?

    ?? ? ? 至此,Android系統(tǒng)匿名共享內(nèi)存利用Binder進程間通信機制來實現(xiàn)進程間共享的學習就結(jié)束了,整個Android系統(tǒng)匿名共享內(nèi)存機制的學習也完成了,希望對讀者有所幫助,重新學習Android系統(tǒng)匿名共享內(nèi)存機制請回到Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃一文。





    本文轉(zhuǎn)自 Luoshengyang 51CTO博客,原文鏈接:http://blog.51cto.com/shyluo/965501,如需轉(zhuǎn)載請自行聯(lián)系原作者

    總結(jié)

    以上是生活随笔為你收集整理的Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。