在第二篇中说到了 BpBinder::transact 调用了 IPCThreadState::self()->transact,我们看下具体实现细节,注意这里是 BpBinder 的 transact
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
//数据检查
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
if (err == NO_ERROR) {
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
//等待
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
//oneway,不需要等待replay场景
err = waitForResponse(NULL, NULL);
}
return err;
}
handle 表示驱动的值,code 是传输的状态码,data 是传入的数据,reply 是返回数据,flags 标志
主要的函数就是 writeTransactionData 和 waitForResponse
writeTransactionData
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
//申请一个binder_transaction_data 格式的tr
binder_transaction_data tr;
//设置它的属性
tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
//检查传入的数据是否正确
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
//读取data赋值给tr
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
//
} else {
return (mLastError = err);
}
//cmd = BC_TRANSACTION
mOut.writeInt32(cmd);
//写入binder_transaction_data 数据
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
binder_transaction_data 这个结构体对象很重要,它拥有的属性:
struct binder_transaction_data {
union {
__u32 handle;//用它可以找到对应的binder_ref,通过它找到目标的binder_node,最后找到目标进程binder_proc
binder_uintptr_t ptr;binder_node的指针
} target;
binder_uintptr_t cookie;
__u32 code;//Client端与Server端双方约定的命令码,让Server端调用对应的方法处理数据。
__u32 flags;
pid_t sender_pid;//发送端进程的pid
uid_t sender_euid;//发送端进程的uid
binder_size_t data_size;//Parcel中数据的大小
binder_size_t offsets_size;//Parcel中flat_binder_object个数
union {
struct {
binder_uintptr_t buffer;//数据对应的指针。
binder_uintptr_t offsets;//flat_binder_object对应的偏移量
} ptr;
__u8 buf[8];
} data;
};
通过 writeTra

本文详细剖析了Android系统中Binder通信机制的实现原理,从BpBinder::transact调用开始,深入探讨了IPCThreadState::transact的具体实现,包括writeTransactionData和waitForResponse等关键函数的工作流程。同时,文章还解释了binder_transaction_data结构体的作用,以及Binder驱动如何通过ioctl与用户空间进行数据交互,最终实现跨进程通信。
最低0.47元/天 解锁文章
357

被折叠的 条评论
为什么被折叠?



