1. Parcel的原理是把数据按照类型和顺序写在内存中,取数据的时候,按照同样的顺序即可
2.存储数据的时候,以4字节为基本单位进行内存对齐
3.采用memcpy以及
*reinterpret_cast<T*>(mData+mDataPos) = val; 的方式写内存数据
4.采用realloc的方式扩展内存大小
5.和binder纠缠在一起了,传送文件描述符的时候,对数据动了手脚,根据原fd在目标进程中创建了一个对应的fd,
由于是在底层(binder驱动)进行的操作,为了让服务端不作特殊操作,就把新的fd修改到了Parcel数据里传送到了服务端
由于读数据的时候,都是按照给定的大小去读,下面代码里的*reinterpret_cast<uint32_t*>(data+padded-4) &= mask[padded-len];
是可以去掉的,写在这里会让人难以理解,如果要初始化扩展出来的字节,直接将其memset为0即可,
写成这样到显得晦涩
void* Parcel::writeInplace(size_t len) { if (len > INT32_MAX) { // don't accept size_t values which may have come from an // inadvertent conversion from a negative int. return NULL; } const size_t padded = pad_size(len); // sanity check for integer overflow if (mDataPos+padded < mDataPos) { return NULL; } if ((mDataPos+padded) <= mDataCapacity) { restart_write: //printf("Writing %ld bytes, padded to %ld\n", len, padded); uint8_t* const data = mData+mDataPos; // Need to pad at end? if (padded != len) { #if BYTE_ORDER == BIG_ENDIAN static const uint32_t mask[4] = { 0x00000000, 0xffffff00, 0xffff0000, 0xff000000 }; #endif #if BYTE_ORDER == LITTLE_ENDIAN static const uint32_t mask[4] = { 0x00000000, 0x00ffffff, 0x0000ffff, 0x000000ff }; #endif //printf("Applying pad mask: %p to %p\n", (void*)mask[padded-len], // *reinterpret_cast<void**>(data+padded-4)); *reinterpret_cast<uint32_t*>(data+padded-4) &= mask[padded-len]; } finishWrite(padded); return data; } status_t err = growData(padded); if (err == NO_ERROR) goto restart_write; return NULL; }