android Binder详解 (2)

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
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值