binder驅(qū)動(dòng)代碼在drivers/android。在標(biāo)準(zhǔn)linux內(nèi)核下,默認(rèn)是不編譯進(jìn)去的。linux5.17.4 binder版本為8
wanqing@ThinkBook-15:~/data/kernel/linux-5.17.4/drivers/android$ ls *.c
binder_alloc.c binder_alloc_selftest.c binder.c binderfs.c
binder.c和binder_alloc.c是 binder驅(qū)動(dòng)核心文件,至少得編譯這兩個(gè)文件。
binderfs.c是binderfs文件系統(tǒng),用于命名空間下單獨(dú)掛載binder,現(xiàn)在android系統(tǒng)還沒(méi)用到,看來(lái)谷歌是想android系統(tǒng)跑多個(gè)子系統(tǒng),或者在服務(wù)器上一個(gè)內(nèi)核跑多個(gè)android系統(tǒng)。這對(duì)于群控來(lái)說(shuō)不錯(cuò)。
binder_alloc_selftest.c是用于調(diào)試測(cè)試的,每次ioctl binder fd都會(huì)調(diào)用binder_selftest_alloc測(cè)試。
# SPDX-License-Identifier: GPL-2.0-only
ccflags-y += -I$(src) # needed for trace events
obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o
obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
如果要將binder驅(qū)動(dòng)編譯進(jìn)內(nèi)核,需要在編譯配置文件中設(shè)置,CONFIG_ANDROID_BINDERFS不是必須選項(xiàng),CONFIG_ANDROID_BINDER_DEVICES這里設(shè)置為android10以上的binder配置
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder"
嘗試掛載binder,測(cè)試ok。在最新的內(nèi)核5.17中,如果binderfs編譯進(jìn)去,需要掛載binderfs,不然無(wú)法訪問(wèn)/dev/binder
root@arm64:~# mount -t binder none /dev/binderfs/
root@arm64:~# ls -al /dev/binderfs/
binder features/ vndbinder
binder-control hwbinder
多了一個(gè)binder-control節(jié)點(diǎn),binder-control支持添加binder設(shè)備。更加靈活了。這樣可以不用更改內(nèi)核,添加更改binder設(shè)備,這點(diǎn)改進(jìn)挺好的。
測(cè)試代碼
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fsuid.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/android/binder.h>
#include <linux/android/binderfs.h>
int main() {
int result = 0;
struct binderfs_device device = {0};
struct binder_version version = {0};
printf("binder test\n");
char binderfs_path[512] = "/tmp/binder_XXXXXX";
char device_path[256];
if (mkdtemp(binderfs_path) == NULL){
printf("mktemp %s fail\n",binderfs_path);
result = 1;
goto end;
}
int ret = mount(NULL, binderfs_path, "binder", 0, 0);
if (ret != 0) {
result = 2;
goto rmdir;
}
memcpy(device.name, "my-binder", strlen("my-binder"));
snprintf(device_path, sizeof(device_path), "%s/binder-control", binderfs_path);
int fd = open(device_path, O_RDONLY | O_CLOEXEC);
if(fd<=0){
result = 3;
goto umount;
}
ret = ioctl(fd, BINDER_CTL_ADD, &device);
close(fd);
snprintf(device_path, sizeof(device_path), "%s/my-binder", binderfs_path);
fd = open(device_path, O_CLOEXEC | O_RDONLY);
if(fd<=0){
printf("%s - Failed to open my-binder device\n",
strerror(errno));
result=4;
goto umount;
}
ret = ioctl(fd, BINDER_VERSION, &version);
if(ret<0){
printf("%s - Failed to open perform BINDER_VERSION request\n",
strerror(errno));
result=5;
goto umount;
}
printf("Detected binder version: %d", version.protocol_version);
ret = unlink(device_path);
if(ret!=0){
printf("%s - Failed to delete binder device\n",
strerror(errno));
goto umount;
}
snprintf(device_path, sizeof(device_path), "%s/binder-control", binderfs_path);
ret = unlink(device_path);
if(ret==0){
printf("Managed to delete binder-control device\n");
}
umount:
ret = umount2(binderfs_path, MNT_DETACH);
rmdir:
ret = rmdir(binderfs_path);
end:
printf("result:%d\n",result);
return result;
}