进程获得的fd是进程fd table中的index, 在fd table中记录了file指针, file对象保留在kernel空间中.
因此不同进程间传递fd本身并没有什么意义.
binder通过parcel传递fd的本质, 是将源进程的fd table中对应项指针, 记录到target进程的fd table中.
client端add的fd和server端读出的是两个值. 但实际上指向的是一个file对象.
这有些类似于dup(), 不过dup是在同一进程中复制两个fd, 指向一个file对象. 而binder传递后是在两个进程中.
android进程在fork之后, 会构造processState, 在其构造函数中首先open binder, 之后执行mmap.
这个mmap调用在binder driver这一层会将源进程的current->files保存到对应binder_proc的files中.
proc->files = get_files_struct(current);
到了真正transact的时候, binder driver会判断flat_binder_object类型, 如果是BINDER_TYPE_FD,
就通过fget(fd)获得源binder_proc中files记录的file对象, 并通过task_fd_install保存到目标进程的fd table中.
1633 case BINDER_TYPE_FD: {
1634 int target_fd;
1635 struct file *file;
1636
1651 file = fget(fp->handle);
1652 if (file == NULL) {
1653 binder_user_error("%d:%d got transaction with invalid fd, %d\n",
1654 proc->pid, thread->pid, fp->handle);
1655 return_error = BR_FAILED_REPLY;
1656 goto err_fget_failed;
1657 }
1663 target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
1664 if (target_fd < 0) {
1665 fput(file);
1666 return_error = BR_FAILED_REPLY;
1667 goto err_get_unused_fd_failed;
1668 }
1669 task_fd_install(target_proc, target_fd, file);
1674 fp->handle = target_fd;
1675 } break;
也就是说, binder driver替binder通信的另一端在底层打开了这个文件. 只不过, 这个打开不是通常的open方式,
而是在驱动层将已有的file指针复制了过去. 因此, 同dup类似, 两个进程的fd享有相同的file offset和file status flag.