在上一节的视频中,我们在binder驱动中,添加了一些打印信息,我们首先来回忆一下驱动程序的框架。
应用程序访问驱动是通过open。read。write,ioctrol等,在驱动程序也存在对应的drv_open。drv_read。drv_write,drv_ioctrol等,一般驱动的编写流程如下:
1.构造文件描述符file_operations结构体。
2.告诉内核,即注册驱动,调用register_chardev()。
3.入口函数调用register_chardev()。
打开SDK\kernel-release-4.4\drivers\android\binder.c从binder_init函数看起(只摘选重要部分):
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,
};
static int __init binder_init(void)
ret = init_binder_device(device_name);
binder_device->miscdev.fops = &binder_fops;
misc_register(&binder_device->miscdev);//注册binder驱动
现在在我们进入service_manager.c文件,从main函数开始:
int main()
bs = binder_open(128*1024);
/*打开binder驱动程序*/
bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
/*告诉binder驱动自己是一个service_manager,当其他的应用程序向handel为0的
进程发送数据的时候,即使给service_manager进程发送数据,方便binder找到service_manager进程*/
if (binder_become_context_manager(bs)) {
binder_loop(bs, svcmgr_handler);
/*发起一个写操作*/
readbuf[0] = BC_ENTER_LOOPER;//对所有进程进入监视读操作
binder_write(bs, readbuf, sizeof(uint32_t));
/*代表不需要写入什么东西*/
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
for (;;) {
/*发起一个读操作,但是我们首先运行的进程为service_manager进程
所以运行到这里,进入休眠状态,等待其他的进程写操作,如我们编写的
test_server.c进程*/
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
上面是service_manager进程的流程,在其调用open的时候,会导致内核drivers\android\binder.c驱动中的binder_open被调用:
static int binder_open(struct inode *nodp, struct file *filp)
/*对于每个进程,在调用open函数的时候,都会根据其进程信息构造一个
binder_proc *proc结构体*/
struct binder_proc *proc;
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
下面是service_manager.c与test_server.c交互的一个简单图示:
binder驱动的交互会涉及两个进程,A进程发送一个消息(BC_TRANSACTION)给进程B,B就收到((BR_TRANSACTION))处理完之后也会回复一个消息(BC_REPLY)给A,最后A接收到一个(BR_REPLY),只有这几个消息是涉及到进程之间的通信的,其他的消息(BC_xxxx或者BR_xxxx),都是进程和驱动之间的交互,用于改变或者报告状态。简单的图示如下:
在test_server.c执行mmap之后,他会发起一个写操作,命令为BC_TRANSACTION:
图上的那些会被放入service_manager的todo链表。我们知道每个struct binder_proc *proc中都存在一个todo链表,然后test_server还会唤醒service_manager。
前面书说道service_manager进入休眠状态,现在就被唤醒了,然后他就能到上图的那些数据,那些数据中,包含了服务的名称等等。等service_manager处理完之后,service_manager会发送一个BC_REPLY的消息,告诉test_server。