你的位置:首页 > 操作系统

[操作系统]android 进程间通信数据(二)

Serialize是java原生就自带的东西,我们可以看到android的源码

所以看看android是如何实现parcel的,这对我们自己代码设计有什么启发。

Parcel:

在android中,parcel的源码如下:

Frameworks/base/core/java/android/os/Parcel.java

  /**   * Write an integer value into the parcel at the current dataPosition(),   * growing dataCapacity() if needed.   */  public final void writeInt(int val) {    nativeWriteInt(mNativePtr, val);  }  /**   * Write a long integer value into the parcel at the current dataPosition(),   * growing dataCapacity() if needed.   */  public final void writeLong(long val) {    nativeWriteLong(mNativePtr, val);  }

常见方法:

       obtain()           获得一个新的parcel ,相当于new一个对象      dataSize()          得到当前parcel对象的实际存储空间      dataCapacity()        得到当前parcel对象的已分配的存储空间, >=dataSize()值 (以空间换时间)      dataPostion()        获得当前parcel对象的偏移量(类似于文件流指针的偏移量)      setDataPosition()      设置偏移量      recyle()           清空、回收parcel对象的内存      writeInt(int)        写入一个整数      writeFloat(float)      写入一个浮点数      writeDouble(double)      写入一个双精度数      writeString(string)     写入一个字符串     当然,还有更多的writeXXX()方法,与之对应的就是readXXX(),具体方法请参阅SDK。     其中几个值得注意的方法为:       writeException()       在Parcel队头写入一个异常       writeException()       Parcel队头写入“无异常“       readException()       在Parcel队头读取,若读取值为异常,则抛出该异常;否则,程序正常运行。

我们来分析下:

status_t Parcel::writeInt32(int32_t val){  return writeAligned(val);}

template<class T>status_t Parcel::writeAligned(T val) {  COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));  if ((mDataPos+sizeof(val)) <= mDataCapacity) {restart_write:    *reinterpret_cast<T*>(mData+mDataPos) = val;    return finishWrite(sizeof(val));  }  status_t err = growData(sizeof(val));  if (err == NO_ERROR) goto restart_write;  return err;}

我们来分析writeAligned:

首先是

#define PAD_SIZE(s) (((s)+3)&~3)

 &~3:

考虑16进制,~3 -> 0x11111100 在做&

也就是说前面6位不变,最后2位为0.

或者说,把最后2位变成0.也就是4的倍数。

+3的目的是,把当前的值向上取最近的整除4的值,如果本身就是那就不变。

所以就和宏的目的就是按4字节对齐!

所以writeAligned是写入4字节对齐的内容。

常见的是int32 和int64等。

status_t Parcel::growData(size_t len){  size_t newSize = ((mDataSize+len)*3)/2;  return (newSize <= mDataSize)      ? (status_t) NO_MEMORY      : continueWrite(newSize);}

当内存不够的时候,会申请一块3/2块大小的内存,使得现在parcel可以使用。

所以parcel本质的是最内存的操作,而且操作位memcpy等。

查看continueWrite函数,由于很复杂,就不列出来了,

看看关键的地方:

      size_t* objects =        (size_t*)realloc(mObjects, objectsSize*sizeof(size_t));

扩大内存,啊哈。就是这个地方了。

所以整个parcel的读写都在内存中操作的。