2.3 SampleService启动(main函数实现)
service的启动实际就是需要编写一个可执行程序来运行service。
还是以surfaceflinger为例,surfaceflinger的main函数在frameworks/native/service/surfacefllinger/main_surfaceflinger.cpp:
int main(int argc, char** argv) {
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
#endif
set_sched_policy(0, SP_FOREGROUND);
// initialize before clients can connect
flinger->init();
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
// run in this thread
flinger->run();
return 0;
}
大致看一下这个函数,主要牵扯到了了ProcessState和ServiceManager,其他主要是一些surfaceflinger 初始化动作等。
ServiceManager::addService()所做的动作是把service注册到servicemanager,这种中间是如何工作的,我们等到后面再分析。
这里先看下ProcessState。
2.3.1 ProcessState
ProcessState头文件在frameworks/native/include/binder/ProcessState.h,下面看下这个类中被调用到的函数:ProcessState::self(),setThreadPoolMaxThreadCount(),startThreadPool()。
ProcessState::self()
这个函数不用仔细说了,static函数,加上ProcessState的构造,析构函数的私有化,这是个典型的单例模式的使用。
也就是说,在当前进程中只有一个ProcessState对象,通过self()函数来访问这个唯一的对象。我们看看ProcessState的构造中做了什么:
ProcessState::ProcessState()
: <span style="color:#FF0000;">mDriverFD(open_driver())</span>
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// XXX Ideally, there should be a specific define for whether we
// have mmap (or whether we could possibly have the kernel module
// availabla).
#if !defined(HAVE_WIN32_IPC)
<span style="color:#FF0000;"> // mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);</span>
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
#else
mDriverFD = -1;
#endif
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
构造中,主要是初始化mDriverFD和初始化了mVMStart。
先看mDriverFD的初始化,mDriverFD是从open_driver()中得到的:
static int open_driver()
{
int fd = open("/dev/binder", O_RDWR);
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
int vers;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("<span style="color:#FF0000;">Binder ioctl to set max threads failed</span>: %s", strerror(errno));
}
} else {
ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
这个函数中,我们看到了这边open了/dev/binder,也就是binder虚拟设备(后面我们就简称为binder了)。
然后获取了binder version,进行比较,之后进行了BINDER_SET_MAX_THREADS的操作。
BINDER_SET_MAX_THREADS这个操作,我们从log中可以看到是设置一个max thread,但是这个thread具体指什么thread还是很模糊的,先不去理会,后续分析binder的时候再注意一下。
再来看看mVMStart:
mVMStart的初始化就是一个mmap,从mDriverFD也就是binder中mmap出来一块BINDER_VM_SIZE大小的内存,返回出来的就是这块内存的指针。
代码中是找不到直接操作这个地址的地方的,看来具体的如何使用也要到后面具体分析才能看明白。
ProcessState::setThreadPoolMaxThreadCount()
status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
status_t result = NO_ERROR;
if (<span style="color:#FF0000;">ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) == -1</span>) {
result = -errno;
ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
}
return result;
}
这边和open_driver()中一样,调用了BINDER_SET_MAX_THREADS。操作具体含义不清楚,我们在SampleService中可以暂时照着样子去写。
ProcessState::startThreadPool()
startThreadPool()的调用逻辑中,最重要的是调用了spawnPooledThread()启动了一个新的PoolThread,我们看看PoolThread里面做了什么。
PoolThread的loop函数在frameworks/native/libs/binder/ProcessState.cpp中,
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
threadloop()就是调用了IPCThreadState::joinThreadPool(),要了解threadloop做了什么,还要了解下IPCThreadState。
2.3.2 IPCThreadState
IPCThreadState的头文件在frameworks/natvie/include/binder/IPCThreadState.h。
2.3.2.1 static IPCThreadState* self()
IPCThreadState的构造析构函数都是private,只能通过self()来获得它的对象,看起来也是一个单例模式,但是实际有些差异:
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = <span style="color:#FF0000;">(IPCThreadState*)pthread_getspecific(k);</span>
i