2012-10-12 87 views
1

我想擁有一個共享內存塊(ashmem區域),它是從本機代碼映射和訪問的。我也希望這個塊被幾個應用程序使用。我也希望它能夠在SDK級別7(Android 2.1)上工作NDK中的共享內存區域

有兩條路線。我可以用本地代碼創建一個ashmem區域;但接下來的問題是 - 如何將整型文件描述符傳遞給另一個進程?您可以通過Parcel編組FileDescriptor對象,但無法在原始FD周圍構建對象。還有ParcelFileDescriptor支持構建和檢索整數FD,但相關方法只支持SDK級別12或更高。

或者,我可以創建MemoryFile。有一個fugly way可以在Parcel中傳遞。但是,如何從中檢索文件描述符,以便本地代碼具有mmap()

回答

3

在所有版本的Android自1.5至4.1之後,FileDescriptor都有一個int數據成員,稱爲descriptor。它在早期版本的Android上是私有的,在最近的版本上是私有的。通過一些有意的訪問控制顛覆,你可以通過反射或者通過JNI訪問它。如果是反射,默認情況下,每個都可以通過Field.setAccessible()繞過訪問控制(如果是JNI)。

考慮到這一點,你可以可以圍繞本地FD構建一個FileDescriptor就好了。構建一個空白的,然後設置descriptor。這是Android代碼在構建這些代碼時所做的一小部分工作。

這個骯髒的黑客最終是否會破發,誰知道。幸運的是,這不是我的情況下的核心功能 - 有一些優雅的退化。

如果平臺允許,可以使用支持的ParcelFileDescriptor方法有條件地使用字段訪問hack作爲後備。這樣,這將是相對未來的證據。

0

這是它的工作對我來說有類似的問題,工作時:

而不是使用shmfd =開放(SHM_PATH,O_RDWR),用於創建和獲取文件描述符我

int fd = ashmem_create_region("SharedRegionName", size); 

取代了它和所使用的文件描述符獲得基地址:

int base_address = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 

//寫數據 您可以BASE_ADDRESS從吶傳遞到你的Java代碼tive代碼使用返回描述符的本地函數。

然後我用aidl接口創建一個服務,並使用這個接口綁定來自另一個進程的這個服務。從服務中,我使用ParcelFileDescriptor對象返回到另一個進程。您可以創建ParcelFileDescriptor:

ParcelFileDescriptor desc = ParcelFileDescriptor.fromFd(fd);