binder驱动代码在drivers/android。在标准linux内核下,默认是不编译进去的。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驱动核心文件,至少得编译这两个文件。
binderfs.c是binderfs文件系统,用于命名空间下单独挂载binder,现在android系统还没用到,看来谷歌是想android系统跑多个子系统,或者在服务器上一个内核跑多个android系统。这对于群控来说不错。
binder_alloc_selftest.c是用于调试测试的,每次ioctl binder fd都会调用binder_selftest_alloc测试。
# 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驱动编译进内核,需要在编译配置文件中设置,CONFIG_ANDROID_BINDERFS不是必须选项,CONFIG_ANDROID_BINDER_DEVICES这里设置为android10以上的binder配置
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder"
尝试挂载binder,测试ok。在最新的内核5.17中,如果binderfs编译进去,需要挂载binderfs,不然无法访问/dev/binder
root@arm64:~# mount -t binder none /dev/binderfs/
root@arm64:~# ls -al /dev/binderfs/
binder features/ vndbinder
binder-control hwbinder
多了一个binder-control节点,binder-control支持添加binder设备。更加灵活了。这样可以不用更改内核,添加更改binder设备,这点改进挺好的。
测试代码
#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;
}