Binder驱动注册


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进程空间地址。


任重而道远

你可能感兴趣的:(Binder驱动注册)