SurfaceFlinger启动流程

一、从init.rc文件开始

1、SurfaceFlinger 进程是由 init 进程创建的,运行在独立的 SurfaceFlinger 进程中。init 进程读取 init.rc 文件启动 SurfaceFlinger。

路径: /system/core/rootdir/init.rc

Init.rc 文件在加载的时候会加载所有的core服务

on boot

......

class_start core

**查看下surfaceflinger.rc文件 **路径: frameworks/native/services/surfaceflinger/surfaceflinger.rc

service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
capabilities SYS_NICE
onrestart restart zygote
....

Surfaceflinger.rc中可以看到class core,所以Init.rc 中 class_start core ,就会执行surfaceflinger.rc这个文件。之后会执行Main_surfaceflinger.cpp2、main_surfaceflinger.cpp这个会创建其线程池、进程优先级、线程优先级、surfaceFlinger对象 等相关操作。

int main(int,char**){
signal(SIGPIPE,SIG_IGN); //表示让系统忽略SIGPIPE信号,SIGPIPE信号的默认处理是终止程序

//sf service启动时要设置binder的线程池,用于设置 当前进程用于hwbinder通信的最大线程数:
hardware::configureRpcThreadpool(1 /* maxThreads */,false /* callerWillJoin */);

//启动图形分配器服务
startGraphicsAllocatorService();
//sf进程启动后,限制其进程中binder线程数量为4
ProcessState::self()->setThreadPoolMaxThreadCount(4);

//start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();//开启线程池

//instantiate surfaceflinger
sp<SurfaceFlinger> flinger = surfaceFlinger::createSurfaceFligner();

setpriority(PRIO_PROCESS,0,PRIORITY_URGENT_DISPLAY);//PRIO_PRCESS设置进程优先级,0是当前进程,PRIORITY_URGENT_DISPLAY是优先级档位,

set_sched_policy(0,SP_FOREGROUND);//设置调度策略,优先级

//Put most SufraceFlinger threads in the system-background cpuset
//Keeps us from unnecessarily using big cores
//Do this after the binder thread pool init
if(cpusets_enable()) set_cpuset_policy(0,SP_SYSTEM);//cpu 策略,sf被限制在了小核

//initialize before clients can connect
flinger->init();

//publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());

//添加surfaceflinger服务到 ServiceMananger
sm>addService(String16(SurfaceFlinger::getServiceName()),flinger,false,IServiceManger::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);

//依赖于SF在上面注册,启动DisplayService
startDisplayService();

if(SurfaceFlinger::setSchedFifo(true) != NO_ERROR){
ALOGW("Couldn't set to SCHED_FIFO: %s",strerror(errno));

//run surface flinger in this thread
flinger->run();
return 0;
}

(一)、详细分解hardware::configureRpcThreadpool(1,false);
时序图:

image

1、configureRpcThreadpool用于设置 当前进程用于hwbinder通信的最大线程数
路径:/system/libhidl/transport/HidlTransportSupport.cpp

void configureRpcThreadpool(size_t maxThreads,bool callerWillJoin){
    configureBinderRpcThreadpool(maxThreads,callerWillJoin);
}

路径:system/libhidl/transport/HidlBinderSupport.cpp

void configureBinderRpcThreadpool(size_t maxThreads,bool callerWillJoin){
status_t  ret = ProcessState::self()->setThreadPoolCofiguration(maxThreads,callerWillJoin);
LOG_ALWAYS_FATAL_IF(ret !=ok,”Could not setThreadPoolConfiguration: %d”,ret);
gThreadPoolConfigured = true;
}

2、ProcessState::self()类似 binder 框架里面的流程,在当前进程中初始化 hwbinder
(1)、setThreadPoolConfiguration设置当前进程用于hwBinder 通信的进程数
google是为了HIDL实现一套专用 ProcessState、IPCThreadState、BpHwBinder 。HIDL是用于指定 HAL 和其用户之间的接口的统一接口。
当前进程fd中hwbinder框架的初始化hidl 的 PrcessState、IPCThreadState的代码位置为:
system/libhwbinder/ProcessState.cpp
system/libhwbinder/IPCThreadState.cpp
(2)、self方法里面创建 ProcessState对象

sp<ProcessState> ProcessState::self()
{//加锁,单例实现
    Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {  //C++中的单例模式
        return gProcess;
    }
gProcess = new ProcessState(kDefaultDriver);//创建 ProcessState对象
    return gProcess;
}

ProcessState的构造方法中,会使用 open_driver 方法,去打开 /dev/hwbinder 节点,用来在 kernel 里面初始化 此进程 相关hwbinder数据结构, 并将打开 hwbinder 节点的 fd 保存在mDriverFD 变量里面,之后通过此 fd来和 kernel内部的驱动进行通信。

(3)、构造方法

ProcessState::ProcessState(const char *driver)
   :mDriverName(String8(driver))
,mDriverFD(open_driver(driver))
   , mVMStart(MAP_FAILED)
   , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
   , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
   , mExecutingThreadsCount(0)
   , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
   , mStarvationStartTimeMs(0)
   , mBinderContextCheckFunc(nullptr)
   , mBinderContextUserData(nullptr)
   , mThreadPoolStarted(false)
   , mSpawnThreadOnStart(true)
   , mThreadPoolSeq(1)
   , mCallRestriction(CalRestriction::NONE)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using /dev/hwbinder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
       mDriverName.clear();
        }
    }
}

(4)、open_driver会直接去打开 /dev/hwbinder 节点。
此方法会通知hwbinder驱动,在kernel中初始化 此进程中 hwBinder相关的数据结构。

static int open_driver(const char *dirver)
{
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers); //通知将此进程中的binder版本,与kernel的版本进行对比
        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(%d) does not match user space protocol(%d)!", vers, BINDER_CURRENT_PROTOCOL_VERSION);
            close(fd);
            fd = -1;
        }
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); //设置fd进程可用于hwBinder通信的最大进程数
        if (result == -1) {
            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        ALOGW("Opening '/dev/hwbinder' failed: %s\n", strerror(errno));
    }
    return fd;
}

BINDER_VERSION将此进程中的binder版本,通过ioctl 方法告诉kernel,与kernel的版本进行对比
BINDER_SET_MAX_THREADS设置此进程给用于hwbinder 通信的线程数,为BINDER_SET_MAX_THREADS

(5)、ProcessState::self()完成下来看下 setThreadPoolConfiguration(maxThreads,callerWillJoin);
通过setThreadPoolConfiguration,对通信线程数进行了修改。

status_t ProcessState::setThreadPoolConfiguration(size_t maxThreads,bool callerJoinsPool){
//如果其他线程要加入binder线程池,线程池至少要有一个线程。
LOG_ALWAYS_FATAL_IF(maxThreads < 1, "Binder threadpool must have a minimum of one thread.");
size_t threadsToAllocate = maxThreads;
//如果调用者要加入线程池,它将向线程池贡献一个线程.这是API契约的一部分。
If(callerJoinsPool) threadsToAllocate--;

//如果可以,在线程池启动时从用户空间派生一个线程。这确保在线程池启动时,始终有一个线程可用来启动更多线程。
Bool spawnThreadOnStart = threadsToAllocate > 0;
If(spawnThreadOnStart) threadsToAllocate --;

//The BINDER_SET_MAX__THREADS ioctl really tells the kernel how many threads it’s allowed to spawn,*in addition* to any threads we may have already spawned locally.

//BINDER_SET_MAX_THREADS告诉内核允许生成多少线程,除了已经生成的一些线程。
size_t kernelMaxThreads =  threadsToAllocate;
AutoMutex _l(mLock);

//ioctl执行指令

If(ioctl(mDriverFD,BINDER_SET_MAX_THREADS,&kernelMaxThreads) == -1){
ALOGE(“Binder ioctl to set max threads failed: %s”,strerror(errno));
return -errno;
}

mMaxThreads = maxThreads;
mSpawnThreadOnStart = spawnThreadOnstart;
return NO_ERROR;
}

(二) 、初始化surfaceFlinger

1、sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
路径: frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp

sp<SurfaceFlinger> createSurfaceFlinger(){
static DefaultFactory factory;
return new SurfaceFlinger(factory);
}

通过SurfaceFlingerFactory.cpp创建了一个SurfaceFlinger对象

2、ProcessState:self()->setThreadPoolMaxThreadCount(4)
路径:frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> processState::self(){
     Mutex::Autolock _l(gProcessMutex);
     If(gProcess != nullptr){
    return gProcess;
}
gProcess = new ProcessState(kDefaultDriver);
return gProcess;
}
status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads){
status_t result = NO_ERROR;
If(ioctl(mDriverFD,BINDER_SET_MAX_THREADS,&maxThreads) != -1){
    mMaxThreads = maxThreads;
}else{
    result = -errno;
    ALOE(“Binder ioctl to set max threads failed: %s”,strerror(-result));
}
Return result;
}

surfaceFlinger创建,初始化,运行过程留到下一章。

SurfaceFlingerSurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlingerSurfaceFlinger 服务是在 服务是在 服务是在 SystemSystemSystemSystemSystem 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 SurfaceFlingerSurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlingerSurfaceFlinger 服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 UI 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值