刚开始实习,进入公司所干的事儿虽然和以前没有太大区别,都是看代码调试代码,但是这是与以前所看过的代码都不一样,需要补充相关的基础理论知识,需要静下心来,慢慢学习和补充。
以下是未来几天需要学习的内容:
一、Android 源码中智能指针的分析
在Android 底层运行库层源码中,经常会碰到sp<T>,wp<T>这样的代码,这是Google编写的针对C++指针释放的一种机制,有点类似于JAVA或者C#中垃圾回收机制,当某个对象没有被别人引用后,系统会自动回收。C++一般使用delete回收资源,为什么要使用这种所谓的智能指针呢?原因有二:一是很多程序猿编写C++代码时,忘记释放new出来的对象,或者不知道什么时候该释放这个对象;二是对象已经释放,在其他地方再次引用,造成指针异常;
程序猿在编写程序的时候需要精心设计程序,以避免上面两种问题,例如需要书写很多代码来检查输入的对象是不是已经释放掉了,在释放资源的时候还得考虑是不是其他地方还用到这个对象的引用。在引入智能指针概念以后,这种问题就变得很简单了,程序猿不用担心自己的new出来的对象没有释放而造成内存泄露,也不用担心引用已经释放的对象的引用,这样大大提高了程序的编写效率,同时也提高了系统的稳定性。
说了这么多废话,Google是如何实现所谓的智能指针的呢?
关于智能指针的定义和实现在这两个文件中:
frameworks\base\include\utils\RefBase.h
frameworks\base\libs\utils\RefBase.cpp
关于如何实现就不那么详细的说了!这里仅仅说说实现原理。智能指针通过引用计数来实现智能的,即每个对象在new的时候都会有一个计数值,来记录这个对象被引用的次数,被引用一次,这个计数值加一,当不再使用这个引用时,这个计数值就减一,当计数值减到一的时候,表示这个对象没有被引用了,可以自动销毁了。但是在实际应用中,不会直接孤立的定义一个新的变量来记录一个对象的引用次数,而是将新指针与这个计数值整合到一块,这样还有一个问题就是每次引用的时候主动调用加一,不用的时候调用减一,还是无法解决忘记加一或者忘记减一的问题,问题又回到了原点。在android中,引用计数功能就放在Refbase这个类中,这个类来实现计数的统计,以及对象的销毁,而引用计数何时加减问题,是通过另外一个类sp(Strong Pointer)来实现,通过这个类的构造和析构来实现引用计数的加减,这样就解决了计数的加减问题。如果仅仅使用单一的引用计数无法解决循环引用的问题,比如对象A引用了对象B,而在对象B中又引用了对象A,那么当对象A和B就无法被自动销毁,因为当系统发现A该销毁时,发现A还被B(B从哪里来呀?A中引用B)中引用着,这样系统就无法回收A,同样的道理,也无法回收A,这样就会出现内存泄露的问题了。但是办法总是比问题多,有问题就有解决问题的办法,使用两种计数值:强引用计数和弱引用计数,当父对象引用子对象时就对子对象使用强引用计数,当子对象引用父对象时,就对父对象采用弱引用计数,当强对象引用计数为零,就不管弱对象引用计数是否为零,就强制收回资源,当一个对象只有弱引用计数时,如果要使用这个对象,就要把这个对象提升为强引用计数才可以使用。
这样说还是非常抽象,看看如何使用以后就知道上面的意思。
class RefBase
{//这个类是很sp的基类,里面有引用计数的管理的相关实现
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type
{//这里来处理强弱引用的问题
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
bool attemptIncStrong(const void* id);
//! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
protected:
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_FOREVER = 0x0003
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
weakref_impl* const mRefs;
};
对sp就只用关心其构造函数和析构函数,因为在构造和析构时实现计数加减
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) m_ptr->incStrong(this);
}
template<typename T>
sp<T>::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
下面看看如何使用智能指针以及该注意的问题:
1、智能指针使用必须满足一下两个条件:一是使用智能指针的类必须是继承Refbase这个基类;二是析构函数必须是虚析构函数;
2、使用sp<T> obj=new T() 或者sp<T> obja=objb;注意这里obj是一个sp对象,不是一个指针(不管前一种方式还是第二种方式,都调用了sp的构造函数,实现计数值加减),因此当这个对象生命周期结束后,就会自动调用析构函数,来析构这个对象。
3、不要使用delete来删除sp对象,一定要注意这里的obj是一个对象,而不是一个指针。
到这里,需要问到,T对象上那里去了,T对象被保存到sp对象中的成员变量中m_ptr;
二、Android中进程间通信Binder机制分析
进程间通信机制有多种方式,常见的有基于共享内存、管道、基于套接字进程间通信机制,在Android中使用Binder机制实现进程间通信,相对于基于Socket和管道等传统的进程间通信机制,Binder机制更加系统化,易用性更好,进程间通信就像函数调用一样,实现结构化参数和返回值的传递。Binder机制并不是新提出的概念,而是基于OpenBinder实现来的,为了避开OpenBinder的许可问题,Google重新开发了一套Binder实现,是基于Apache协议发布的。
实现Binder进程通信由:服务端、客户端、Binder驱动和ServiceManager四个组件组成,服务器和客户端当然就是进程间通信的两个进程。下图给出了这四个组件在框架层的关系图:
服务端和客户端都是通过给底层Binder驱动通信来间接实现进程间通信的。Binder驱动程序是整个Binder机制的核心。
三、Android中Camera系统架构分析
四、Android中Surface系统分析