Binder驱动注册
Android进程间利用Binder机制实现通信,在App进程中,调用ioctl方法使程序陷入内核态执行,ioctl是用户态程序控制设备的一个系统调用,既然这样,肯定需要虚拟一个设备,通过设备fd文件描述符操作,虚拟设备不存在任何硬件。
int ioctl(int fd, ind cmd, …);
fd是打开的设备文件描述符,open返回值,cmd是命令参数,第三个参数是指针类型,指向用户态的内存,用于参数传递。
ioctl的内核态方法是unlock_ioctl和compat_ioctl。
初始化结构体file_operations,将unlocked_ioctl、compat_ioctl、open、mmap等内核方法赋值成自定义binder_xxx方法。
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
};
用户态ioctl方法与内核态binder_ioctl方法通过file_operations结构体联系。结构体中每个字段是一个函数指针,指向用户空间对Binder驱动的操作。
binder_poll,poll系统调用。
binder_mmap,内存映射mmap系统调用。
binder_open,打开Binder设备对应open(“/dev/binder”)。
binder_ioctl,ioctl系统调用。
device_initcall调用binder_init方法向内核注册Binder驱动设备,字符型设备驱动。
static int __init binder_init(void)
debugfs_create_dir 和 debugfs_create_file 函数创建debugfs对应的文件
ret = misc_register(&binder_miscdev);
misc_register注册binder_miscdev结构体。
static struct miscdevice binder_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = " binder ",
.fops = &binder_fops//指向结构体file_operations。
};
设备名称是binder,驱动文件是/dev/binder,指定设备fops是file_operations结构体。
打开Binder驱动设备
servicemanager是Binder管理进程,在进程main方法中,触发binder_open方法,负责打开Binder驱动文件。
servicemanager进程main方法。
struct binder_state *bs;
bs = binder_open(128*1024);
servicemanager#binder_open负责通过open系统调用打开Binder驱动设备。将文件描述符fd保存在结构体binder_state中。
struct binder_state *binder_open(size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return NULL;
}
bs->fd = open("/dev/binder", O_RDWR);
if (bs->fd < 0) {
goto fail_open;
}
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
goto fail_open;
}
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
goto fail_map;
}
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return NULL;
}
- binder_state结构体分配内存。
- open系统调用打开驱动,驱动文件为/dev/binder,O_RDWR打开方式为可读可写。
在驱动层调用binder_open方法,主要功能是创建binder_proc节点,并保存到文件句柄的private_data中filp->private_data = proc。 - ioctl系统调用向驱动发送指令BINDER_VERSION,在驱动层调用binder_ioctl方法,验证Binder协议版本,保存在指针vers中。
- 用户空间与内核空间内存映射。
start:指向欲映射的内存起始地址,通常是Null。
mapsize:映射内存大小。
prot:映射区域保护方式,PROT_READ 映射区域可被读取。
flag:影响映射区域的特性,MAP_PRIVATE,对映射区域的写入操作会产生一个映射文件的复制
fd:文件句柄。
offsize:映射文件偏移量,通常是0。
映射成功后,返回映射到进程空间的地址(用户空间的地址)。
将Binder驱动设备文件fd的部分内存(mapsize大小),映射到servicemanager进程空间,字节128K,映射文件地址偏移从0开始。在servicemanager进程可以通过返回的映射的地址操作内核层Binder驱动。
最后binder_open方法返回binder_state结构体指针。
binder_state结构体存储binder驱动文件句柄fd,用户空间映射到内核的起始地址mapped(这块地址在servicemanager进程中),映射内存大小mapsize。综上:将一块128K的内核空间地址映射到servicemanager进程空间地址。
任重而道远