binder是android專屬的一種IPC機制,它是在/system/bin/servicemanager進程(可以用ps看到)中完成初始化的,它的父進程是init.
1. 代碼:
frameworks\base\cmds\servicemanager\,這個目錄下,有service_manager.c,binder.c。
(1) 在service_manager.c中,有main函數,代碼如下:
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
(2) binder_open: 位於binder.c中,binder_open函數實現如下:
struct binder_state *binder_open(unsigned mapsize)
{
struct binder_state *bs;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return 0;
}
bs->fd = open("/dev/binder", O_RDWR);
if (bs->fd < 0) {
fprintf(stderr,"binder: cannot open device (%s)\n",
strerror(errno));
goto fail_open;
}
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
fprintf(stderr,"binder: cannot map device (%s)\n",
strerror(errno));
goto fail_map;
}
/* TODO: check version */
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return 0;
}
2. 說明:
(1) 在frameworks\base\cmds\servicemanager目錄下的Android.mk中,指定產生的模組為servicemanager:
LOCAL_MODULE := servicemanager //
(2) dev/binder會映射到一塊記憶體虛擬空間中,通過mmap系統調用來實現。
(3) binder.c中還提供了一系列函數,用於支援binder的訪問。
(4) binder通訊機制的實現中,是用ioctl的方式與核心進行互動的。
(5) binder的初始化一定是在jvm的初始化之前,因為jvm初始化一直到上層的system_server的過程中,會有啟動很多的service,這些service都會去用到binder。
(6) servicemanager這個進程的許可權是system,這個通過ps也能看出來,它是在init.rc中指定的。
3. 補充:
mmap的使用:
#include <sys/mman.h>
(1) void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)。
描述: 把檔案或者裝置映射到記憶體。這個函數在調用進程的虛擬位址空間中建立一區塊對應地區。
參數說明:
addr: 指定映射地區的首地址, 如果addr是NULL,那麼由核心來選擇一個地址來建立映射的地區,否則建立的時候會儘可能地使用addr的地址。在linux系統中,建立映射的時候應該是在下一個頁面的邊界建立,addr是NULL的時候,程式的可移植性最好。
length:指定映射地區的長度。
offset:指定從檔案的哪個位移位置開始映射,offset必須是頁面大小的整數倍頁面的大小可以由sysconf(_SC_PAGE_SIZE)來返回。
flags指定地區在不同進程之間的共用方式,以及地區是否同步到相應的檔案等等。
fd: 檔案描述符.在binder中,指的就是:bs->fd = open("/dev/binder", O_RDWR)。
傳回值: 這個函數返回新建立的頁面的地址。成功的時候這個函數返回0。 失敗的時候,返回-1。
(2) int munmap(void *addr, size_t length);
作用: munmap 取消address指定位址範圍的映射。以後再引用取消的映射的時候就會導致非法記憶體的訪問。這裡address應該是頁面的整數倍。 成功的時候這個函數返回0。 失敗的時候,返回-1.。