解读Android 服务启动过程

http://blog.sina.com.cn/s/blog_606334a20100gqk4.html

看下面这个main函数,摘自main_surfaceflinger.cpp,此函数是启动SurfaceFlinger服务,并准备服务所需要的线程池。


int main(int argc, char** argv)
{
 
    sp<ProcessState>proc(ProcessState::self());
      sp<IServiceManager> sm =defaultServiceManager();
      LOGI("ServiceManager: %p", sm.get());
      SurfaceFlinger::instantiate();
      ProcessState::self()->startThreadPool();
      IPCThreadState::self()->joinThreadPool();
}

虽然没几句话,但底下可是干了不少事,可以说每一句都暗藏玄机。

第一句:sp<ProcessState>proc(ProcessState::self());
这是个strong pointer的声明,初始化用了copy constructor。但proc没人用。为什么这么做?
这里使用的copy constructor能增加引用计数。计数大于0的强指针不会自动消失。
这里的关键还不在于强指针,而在于ProcessState的构造函数执行时,有很多副作用,其中之一就是打开binder设备,取得文件描述符,并为此fd做mmap,获得内存空间以存放事务数据结构。
此外,ProcessState是个比较纯粹的封装,把跟进程/线程有关的内容全放这了。

第二句:sp<IServiceManager> sm =defaultServiceManager();
这句同样引入了一个强指针,指向默认的ServiceManager,同样是个单体,以后用着方便。
看一下实现:
gDefaultServiceManager =interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
注意这里的interface_cast从IBinder取得IServiceManager接口。
具体怎么取得ContextObject得看binder的驱动。

第三句:LOGI("ServiceManager: %p", sm.get());
记录。这句话彻底搞明白,得看log驱动程序,此处从略。

第四句:SurfaceFlinger::instantiate();
这句话似乎是实例化SurfaceFlinger,instantiate函数就一句话:
defaultServiceManager()->addService(String16("SurfaceFlinger"),new SurfaceFlinger());
defaultServiceManager已经有了,到这就省点事,直接调用addService函数。
addService函数复杂一些:
virtual status_t addService(const String16& name,const sp<IBinder>&service)
      {
              Parcel data, reply;
              data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
              data.writeString16(name);
              data.writeStrongBinder(service);
              status_t err =remote()->transact(ADD_SERVICE_TRANSACTION, data,&reply);
              return err == NO_ERROR ? reply.readInt32() : err;
      }
这里要做的,简单地说,就是注册SurfaceFlinger服务,以使得后来的请求知道找谁了。注意addService的第二个参数接收的是个IBinder对象,这具体说得涉及到binder实现的细节。

第五句:ProcessState::self()->startThreadPool();
这句比较奇怪。因为startThreadPool函数调用spawnPooledThread,后者调用PoolThread,后者返回一个Thread对象,接着会调用这个对象的run函数。Thread的run函数run的什么呢?
run的内容是threadLoop函数,后者就一句话:
IPCThreadState::self()->joinThreadPool(mIsMain);
此时mIsMain是true,语义是进入looper。虽说创建了一个pool,但pool里只有一个线程。程序到这里应该是进入binder事务循环了。
在do循环里,需要从binder驱动获得请求,就是ioctl的BINDER_WRITE_READ操作的结果,根据此返回数据,来执行规定动作(executeCommand调用)。后者是binder协议的目的所在,执行对用户有用的动作,这有用的动作,通过IBinder接口的transact函数。目标对象或者是注册的服务,或者是defaultServiceManager。

第六句:IPCThreadState::self()->joinThreadPool();
这句也比较奇怪。此句和第五句最终效果是一样,都是调用IPCThreadState的joinThreadPool函数,默认参数是true,同样是进入looper的意思。为什么同样的事做两遍?大概上一句是让创建的线程干活,而本句是主线程直接干活。

说奇怪,不仅是因为重复做事,还因为根本看不出线程到底是个什么东西,这里的线程由Thread定义,显然不是pthread,但用了相似的语言,比如join,mutex之类,猛一看,还以为会真的出来pthread线程池呢,到最后连线程的影子也没看到。不过,考虑到binder是个同步协议,又主要用在嵌入式设备里,顺序化倒也没什么损失。也许Thread语义以后会改变。

循此逻辑,把最后一句注释掉,应该是不影响SurfaceFlinger服务的,实验证明确实是这样。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值