文档库 最新最全的文档下载
当前位置:文档库 › Spark集群启动之Master、Worker启动流程源码分析

Spark集群启动之Master、Worker启动流程源码分析

Spark集群启动之Master、Worker启动流程源码分析
Spark集群启动之Master、Worker启动流程源码分析

Spark集群启动之Master、Worker启动

流程源码分析

Spark集群启动Master可以使用脚本启动:start-master,shell脚本细节自行查看。

最终启动命令为:Java -cp /home/daxin/bigdata/spark/conf/:/home/daxin/bigdata/spark/jars/*:/home/daxin/bigdata/Hadoop/et c/hadoop/ -Xmx1g -XX:MaxPermSize=256m org.apache.spark.deploy.master.Master --host node --port 7077 --webui-port 8080

最终转换为java命令启动Master的过程,所以我们就需要查看一下Master的main方法代码如下:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

val systemName = "sparkMaster"

private val actorName = "Master"

/**

* spark-class脚本调用,启动master

*

* @param argStrings

*/

def main(argStrings: Array[String]) {

SignalLogger.register(log)

//参数配置准备

val conf = new SparkConf

val args = new MasterArguments(argStrings, conf)

//创建actorSystem

// (actorSystem, boundPort, portsResponse.webUIPort, portsResponse.restPort)

val (actorSystem, _, _, _) = startSystemAndActor(args.host, args.port, args.webUiPort, conf) actorSystem.awaitTermination()

}

通过代码可以可以知道调用startSystemAndActor方法完成ActorSystem和Actor的创建。startSystemAndActor方法中调用

[java] view plain copy 在CODE上查看代码片派生到我的代码片

val (actorSystem, boundPort) = AkkaUtils.createActorSystem(systemName, host, port, conf = conf, securityManager = securityMgr)

完成ActorSystem的创建,然后调用:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

val actor = actorSystem.actorOf(Props(classOf[Master], host, boundPort, webUiPort, securityMgr,

conf), actorName)

完成在该actorSystem中对actor的创建。然后执行Master的声明周期方法preStart: [java] view plain copy 在CODE上查看代码片派生到我的代码片

override def preStart() {

logInfo("Starting Spark master at " + masterUrl)

logInfo(s"Running Spark version ${org.apache.spark.SPARK_VERSION}")

// Listen for remote client disconnection events, since they don't go through Akka's watch() context.system.eventStream.subscribe(self, classOf[RemotingLifecycleEvent])

webUi.bind()

masterWebUiUrl = "http://" + masterPublicAddress + ":" + webUi.boundPort

/**

* 定时器,定义给自己发送心跳去检查是否有超超时的worker,有的话移除超时Worker。

*/

context.system.scheduler.schedule(0 millis, WORKER_TIMEOUT millis, self, CheckForWorkerTimeOut)

masterMetricsSystem.registerSource(masterSource)

masterMetricsSystem.start()

applicationMetricsSystem.start()

// Attach the master and app metrics servlet handler to the web ui after the metrics systems are started.

masterMetricsSystem.getServletHandlers.foreach(webUi.attachHandler)

applicationMetricsSystem.getServletHandlers.foreach(webUi.attachHandler)

/**

* 高可用时候,元数据共享选择持久化引擎,分为ZOOKEEPER、FILESYSTEM、CUSTOM

*/

val (persistenceEngine_, leaderElectionAgent_) = RECOVERY_MODE match {

case "ZOOKEEPER" =>

logInfo("Persisting recovery state to ZooKeeper")

val zkFactory =

new ZooKeeperRecoveryModeFactory(conf, SerializationExtension(context.system))

(zkFactory.createPersistenceEngine(), zkFactory.createLeaderElectionAgent(this))

case "FILESYSTEM" =>

val fsFactory =

new FileSystemRecoveryModeFactory(conf, SerializationExtension(context.system))

(fsFactory.createPersistenceEngine(), fsFactory.createLeaderElectionAgent(this))

case "CUSTOM" =>

val clazz = Class.forName(conf.get("spark.deploy.recoveryMode.factory"))

val factory = clazz.getConstructor(conf.getClass, Serialization.getClass)

.newInstance(conf, SerializationExtension(context.system))

.asInstanceOf[StandaloneRecoveryModeFactory]

(factory.createPersistenceEngine(), factory.createLeaderElectionAgent(this))

case _ =>

(new BlackHolePersistenceEngine(), new MonarchyLeaderAgent(this)) }

persistenceEngine = persistenceEngine_

leaderElectionAgent = leaderElectionAgent_

}

接下来执行声明周期方法:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

override def receiveWithLogging = {

//高可用选举

case ElectedLeader => {

val (storedApps, storedDrivers, storedWorkers) = persistenceEngine.readPersistedData()

state = if (storedApps.isEmpty && storedDrivers.isEmpty && storedWorkers.isEmpty) {

RecoveryState.ALIVE

} else {

RecoveryState.RECOVERING

}

logInfo("I have been elected leader! New state: " + state)

if (state == RecoveryState.RECOVERING) {

//开始恢复Master方法

beginRecovery(storedApps, storedDrivers, storedWorkers)

recoveryCompletionTask = context.system.scheduler.scheduleOnce(WORKER_TIMEOUT millis, self,

CompleteRecovery)

}

}

case CompleteRecovery => completeRecovery()

case RevokedLeadership => {

logError("Leadership has been revoked -- master shutting down.")

System.exit(0)

}

/**

* Worker发来的注册消息

*/

case RegisterWorker(id, workerHost, workerPort, cores, memory, workerUiPort, publicAddress) => {

logInfo("Registering worker %s:%d with %d cores, %s RAM".format(workerHost, workerPort, cores, Utils.megabytesToString(memory)))

//如果当前Master状态为RecoveryState.STANDBY ,不回应Worker信息。

if (state == RecoveryState.STANDBY) {

// ignore, don't send response

} else if (idToWorker.contains(id)) {

//如果包含WorkerInfo了,回复注册失败信息

sender ! RegisterWorkerFailed("Duplicate worker ID")

} else {

//注册新的Worker信息

val worker = new WorkerInfo(id, workerHost, workerPort, cores, memory, sender, workerUiPort, publicAddress)

if (registerWorker(worker)) {

//完成worker的持久化,以防master宕机之后无法恢复

persistenceEngine.addWorker(worker)

//给Worker发送消息:告诉worker完成注册RegisteredWorker

sender ! RegisteredWorker(masterUrl, masterWebUiUrl)

schedule()

} else {

val workerAddress = worker.actor.path.address

logWarning("Worker registration failed. Attempted to re-register worker at same " +

"address: " + workerAddress)

sender ! RegisterWorkerFailed("Attempted to re-register worker at same address: "

+ workerAddress)

}

}

}

case RequestSubmitDriver(description) => {

if (state != RecoveryState.ALIVE) {

val msg = s"Can only accept driver submissions in ALIVE state. Current state: $state."

sender ! SubmitDriverResponse(false, None, msg)

} else {

logInfo("Driver submitted " + https://www.wendangku.net/doc/cc18956674.html,mand.mainClass)

val driver = createDriver(description)

persistenceEngine.addDriver(driver)

waitingDrivers += driver

drivers.add(driver)

schedule()

// TODO: It might be good to instead have the submission client poll the master to determine

// the current status of the driver. For now it's simply "fire and forget".

sender ! SubmitDriverResponse(true, Some(driver.id),

s"Driver successfully submitted as ${driver.id}")

}

}

case RequestKillDriver(driverId) => {

if (state != RecoveryState.ALIVE) {

val msg = s"Can only kill drivers in ALIVE state. Current state: $state."

sender ! KillDriverResponse(driverId, success = false, msg)

} else {

logInfo("Asked to kill driver " + driverId)

val driver = drivers.find(_.id == driverId)

driver match {

case Some(d) =>

if (waitingDrivers.contains(d)) {

waitingDrivers -= d

self ! DriverStateChanged(driverId, DriverState.KILLED, None)

} else {

// We just notify the worker to kill the driver here. The final bookkeeping occurs

// on the return path when the worker submits a state change back to the master

// to notify it that the driver was successfully killed.

d.worker.foreach { w =>

w.actor ! KillDriver(driverId)

}

}

// TODO: It would be nice for this to be a synchronous response

val msg = s"Kill request for $driverId submitted"

logInfo(msg)

sender ! KillDriverResponse(driverId, success = true, msg)

case None =>

val msg = s"Driver $driverId has already finished or does not exist"

logWarning(msg)

sender ! KillDriverResponse(driverId, success = false, msg)

}

}

}

case RequestDriverStatus(driverId) => {

(drivers ++ completedDrivers).find(_.id == driverId) match {

case Some(driver) =>

sender ! DriverStatusResponse(found = true, Some(driver.state),

driver.worker.map(_.id), driver.worker.map(_.hostPort), driver.exception) case None =>

sender ! DriverStatusResponse(found = false, None, None, None, None)

}

}

/**

* 提交应用给Master,Master启动executor

*

*
(如果没有理解错误的话)description中的command应该是:val command = Command("org.apache.spark.executor.CoarseGrainedExecutorBackend",其余参数略)* 代码位置:类的SparkDeploySchedulerBackend中的command

*

*/

case RegisterApplication(description) => {

if (state == RecoveryState.STANDBY) {

// ignore, don't send response

} else {

logInfo("Registering app " + https://www.wendangku.net/doc/cc18956674.html,)

//TODO 把应用信息存到内存, 重点:sender应该是clientActor

val app = createApplication(description, sender) //sender应该是clientActor

registerApplication(app)

logInfo("Registered app " + https://www.wendangku.net/doc/cc18956674.html, + " with ID " + app.id)

//持久化app,实现容错

persistenceEngine.addApplication(app)

//回复appClient已经注册(这一块不是worker)

sender ! RegisteredApplication(app.id, masterUrl)

//TODO Master开始调度资源,其实就是把任务启动启动到哪些Worker上

schedule()

}

}

//TODO appClient发送来的消息,通知Executor状态

case ExecutorStateChanged(appId, execId, state, message, exitStatus) => {

val execOption = idToApp.get(appId).flatMap(app => app.executors.get(execId))

execOption match {

case Some(exec) => {

val appInfo = idToApp(appId)

exec.state = state

if (state == ExecutorState.RUNNING) {

appInfo.resetRetryCount()

}

// exec.application.driver = driverClient

exec.application.driver ! ExecutorUpdated(execId, state, message, exitStatus)

// 完成状态包括:KILLED, FAILED, LOST, EXITED 注意:这里是完成,不是成功!

if (ExecutorState.isFinished(state)) {

// Remove this https://www.wendangku.net/doc/cc18956674.html,cutor from the worker and app

logInfo(s"Removing executor ${exec.fullId} because it is $state")

appInfo.removeExecutor(exec) //appInfo移除executor

exec.worker.removeExecutor(exec) //worker移除executor

val normalExit = exitStatus == Some(0) //判断是否正常推出

// Only retry certain number of times so we don't go into an infinite loop.

if (!normalExit) {

//异常退出

if (appInfo.incrementRetryCount() < ApplicationState.MAX_NUM_RETRY) {

//当前重试次数是否小于最大重试次数MAX_NUM_RETRY10,如果小于重新调度

schedule()

} else {

//超过最大重启次数

val execs = appInfo.executors.values //获取当前app的所有executors

if (!execs.exists(_.state == ExecutorState.RUNNING)) {

//如果不存在运行的executor的话,直接removeApplication

logError(s"Application ${https://www.wendangku.net/doc/cc18956674.html,} with ID ${appInfo.id} failed " +

s"${appInfo.retryCount} times; removing it")

removeApplication(appInfo, ApplicationState.FAILED)

}

}

}

}

}

//位置状态

case None =>

logWarning(s"Got status update for unknown executor $appId/$execId") }

}

/**

* Worker发送来的消息,告诉Driver当前worker状态

*

*/

case DriverStateChanged(driverId, state, exception) => {

state match {

case DriverState.ERROR | DriverState.FINISHED | DriverState.KILLED | DriverState.FAILED =>

removeDriver(driverId, state, exception)

case _ =>

throw new Exception(s"Received unexpected state update for driver $driverId: $state")

}

}

case Heartbeat(workerId) => {

idToWorker.get(workerId) match {

case Some(workerInfo) =>

https://www.wendangku.net/doc/cc18956674.html,stHeartbeat = System.currentTimeMillis()

case None =>

if (workers.map(_.id).contains(workerId)) {

logWarning(s"Got heartbeat from unregistered worker $workerId." +

" Asking it to re-register.")

sender ! ReconnectWorker(masterUrl)

} else {

logWarning(s"Got heartbeat from unregistered worker $workerId." +

" This worker was never registered, so ignoring the heartbeat.") }

}

}

case MasterChangeAcknowledged(appId) => {

idToApp.get(appId) match {

case Some(app) =>

logInfo("Application has been re-registered: " + appId)

app.state = ApplicationState.WAITING

case None =>

logWarning("Master change ack from unknown app: " + appId)

}

if (canCompleteRecovery) {

completeRecovery()

}

}

case WorkerSchedulerStateResponse(workerId, executors, driverIds) => { idToWorker.get(workerId) match {

case Some(worker) =>

logInfo("Worker has been re-registered: " + workerId)

worker.state = WorkerState.ALIVE

val validExecutors = executors.filter(exec => idToApp.get(exec.appId).isDefined) for (exec <- validExecutors) {

val app = idToApp.get(exec.appId).get

val execInfo = app.addExecutor(worker, exec.cores, Some(exec.execId))

worker.addExecutor(execInfo)

execInfo.copyState(exec)

}

for (driverId <- driverIds) {

drivers.find(_.id == driverId).foreach { driver =>

driver.worker = Some(worker)

driver.state = DriverState.RUNNING

worker.drivers(driverId) = driver

}

}

case None =>

logWarning("Scheduler state from unknown worker: " + workerId)

}

if (canCompleteRecovery) {

completeRecovery()

}

}

case DisassociatedEvent(_, address, _) => {

// The disconnected client could've been either a worker or an app; remove whichever it was logInfo(s"$address got https://www.wendangku.net/doc/cc18956674.html,associated, removing it.")

addressToWorker.get(address).foreach(removeWorker)

addressToApp.get(address).foreach(finishApplication)

if (state == RecoveryState.RECOVERING && canCompleteRecovery) {

completeRecovery()

}

}

case RequestMasterState => {

sender ! MasterStateResponse(

host, port, restServerBoundPort,

workers.toArray, apps.toArray, completedApps.toArray,

drivers.toArray, completedDrivers.toArray, state)

}

case CheckForWorkerTimeOut => {

timeOutDeadWorkers()

}

case BoundPortsRequest => {

sender ! BoundPortsResponse(port, webUi.boundPort, restServerBoundPort)

}

}

补充:关于Master的参数配置在org.apache.spark.util.AkkaUtils$#doCreateActorSystem方法中完成!

接下来看看Worker的启动:

Worker启动脚本有:

1:start-slave.sh 指定masterUrl 只能在本地节点启动worker

2:start-slaves.sh SSH到各个Worker节点启动,里面调用的是slaves.sh脚本

java -cp /home/daxin/bigdata/spark/conf/:/home/daxin/bigdata/spark/jars/*:/home/daxin/bigdata/hadoop/et c/hadoop/ -Xmx1g -XX:MaxPermSize=256m org.apache.spark.deploy.worker.Worker --webui-port 8082 spark://node:7077

同理也是执行Worker的main方法:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

/**

*

* spark启动worker脚本调用main方法执行启动worker

*

* @param argStrings

*/

def main(argStrings: Array[String]) {

//完成配置信息

SignalLogger.register(log)

val conf = new SparkConf

val args = new WorkerArguments(argStrings, conf)

//创建actorSystem

val (actorSystem, _) = startSystemAndActor(args.host, args.port, args.webUiPort, args.cores, args.memory, args.masters, args.workDir)

actorSystem.awaitTermination()

}

同Master的main方法过程,接下来看看Worker的生命周期方法:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

/**

* registered :Actor的声明周期方法

* 在registered中完成向Master的注册

*

*/

override def preStart() {

assert(!registered)

logInfo("Starting Spark worker %s:%d with %d cores, %s RAM".format(host, port, cores, Utils.megabytesToString(memory)))

logInfo(s"Running Spark version ${org.apache.spark.SPARK_VERSION}")

logInfo("https://www.wendangku.net/doc/cc18956674.html,rk home: " + sparkHome)

createWorkDir()

context.system.eventStream.subscribe(self, classOf[RemotingLifecycleEvent]) shuffleService.startIfEnabled()

webUi = new WorkerWebUI(this, workDir, webUiPort)

webUi.bind()

registerWithMaster()//完成向Master的注册

metricsSystem.registerSource(workerSource)

metricsSystem.start()

// Attach the worker metrics servlet handler to the web ui after the metrics system is started. metricsSystem.getServletHandlers.foreach(webUi.attachHandler)

}

android系统开机启动流程分析

一,系统引导bootloader 加电,cpu执行bootloader程序,正常启动系统,加载boot.img【其中包含内核。还有ramdisk】 二,内核kernel bootloader加载kernel,kernel自解压,初始化,载入built-in驱动程序,完成启动。 内核启动后会创建若干内核线程,在后装入并执行程序/sbin/init/,载入init process,切换至用户空间(user-space) 内核zImage解压缩 head.S【这是ARM-Linux运行的第一个文件,这些代码是一个比较独立的代码包裹器。其作用就是解压Linux内核,并将PC指针跳到内核(vmlinux)的第一条指令】首先初始化自解压相关环境(内存等),调用decompress_kernel进行解压,解压后调用start_kernel启动内核【start_kernel是任何版本linux内核的通用初始化函数,它会初始化很多东西,输出linux版本信息,设置体系结构相关的环境,页表结构初始化,设置系 统自陷入口,初始化系统IRQ,初始化核心调度器等等】,最后调用rest_init【rest_init 会调用kernel_init启动init进程(缺省是/init)。然后执行schedule开始任务调度。这个init是由android的./system/core/init下的代码编译出来的,由此进入了android的代码】。 三,Init进程启动 【init是kernel启动的第一个进程,init启动以后,整个android系统就起来了】 init进程启动后,根据init.rc 和init. .rc脚本文件建立几个基本 服务(servicemanager zygote),然后担当property service 的功能 打开.rc文件,解析文件内容。【system/core/init/init.c】将service信息放置到service.list中【system/core/init/init_parser.c】。 建立service进程。【service_start(…) execve(…)】 在init.c中,完成以下工作 1、初始化log系统【解析/init.rc和init.%hardware%.rc文件,在两个 文件解析步骤2时执行“early-init”行动】 2、初始化设备【在/dev下创建所有设备节点,下载firmwares】 3、初始化属性服务器【在两个文件解析步骤2时执行“init”行动】

spark+openfire 源代码部署

spark+openfire二次开发(一) 文章分类:Java编程 1.准备工作: 到官网上下载Openfire 3.6.4,并通过svn下载openfire、Spark和SparkWeb 的源代码 官网地址如下: https://www.wendangku.net/doc/cc18956674.html,/downloads/index.jsp 注意官网上最新的Spark版本是2.5.8,其jdk环境最好使用1.6的版本。 2.环境搭建——spark源码安装配置 双击openfire_3_6_4.exe进行openfire的安装,安装过程很简单,不介绍了。 本例的开发环境是基于Eclipse的。 1)选择File——New——Project——Java Project。 输入项目工程名spark Contents中选择"Create project from existiing source",然后把spark 文件所在的文件夹加进去..

点击Finish。 2)生成Spark: 点击Window::Show View::Ant 右击Ant面板,选择Add Buildfiles 展开spark::build文件夹,选择build.xml,点击"OK" 在Ant面板,展开Spark,双击"release",等一段时间,会提示"Build Successful"。 3)运行Spark: 点击Run::Open Debug Dialog...,出现"Run"窗口 选择"Java Application",右键点击"New"按钮. 在"Main"标签页,将New_configuration换成Spark. 点击Project::Browse按钮,选择Spark,再点OK.

分析Android 开机启动慢的原因

开机启动花了40多秒,正常开机只需要28秒就能开机起来。 内核的启动我没有去分析,另一个同事分析的。我主要是分析从SystemServer启来到开机动画结束显示解锁界面的这段时间,也就是开机动画的第三个动画开始到结束这段时间,这是个比较耗时阶段,一般都在17秒左右(见过牛B的手机,只需5秒)。 SystemServer分两步执行:init1和init2。init1主要是初始化native的服务,代码在sy stem_init.cpp的system_init,初始化了SurfaceFlinger和SensorService这两个native的服务。init2启动的是java的服务,比如ActivityManagerService、WindowManagerService、PackageManagerService等,在这个过程中PackageManagerService用的时间最长,因为PackageManagerService会去扫描特定目录下的jar包和apk文件。 在开机时间需要40多秒的时,从Log上可以看到,从SurfaceFlinger初始化到动画结束,要27秒左右的时间,即从SurfaceFlinger::init的LOGI("SurfaceFlinger is starting")这句Log到void SurfaceFlinger::bootFinished()的LOGI("Boot is finished (%ld ms)", long(ns 2ms(duration)) ),需要27秒左右的时间,这显然是太长了,但到底是慢在哪了呢?应该在个中间的点,二分一下,于是想到了以启动服务前后作为分隔:是服务启动慢了,还是在服务启动后的这段时间慢?以ActivityManagerService的Slog.i(TAG, "System now ready")的这句Log为分割点,对比了一下,在从SurfaceFlinger is starting到System now read y多了7秒左右的时间,这说明SystemServer在init1和init2过程中启动慢了,通过排查,发现在init1启动的时候,花了7秒多的时间,也就是system_init的LOGI("Entered system _init()")到LOGI("System server: starting Android runtime.\n")这段时间用了7秒多,而正常情况是400毫秒便可以初始化完,通过添加Log看到,在SensorService启动时,用了比较长的时间。 不断的添加Log发现,在启动SensorService时候,关闭设备文件变慢了,每次关闭一个/dev/input/下的设备文件需要100ms左右,而SensorService有60~70次的关闭文件,大概有7s左右的时间。 调用流程是: frameworks/base/cmds/system_server/library/system_init.cpp: system_init->SensorServi ce::instantiate frameworks/native/services/sensorservice/SensorService.cpp: void SensorService::onFi rstRef()->SensorDevice& dev(SensorDevice::getInstance()) hardware/libsensors/SensorDevice.cpp: SensorDevice::SensorDevice()->sensors_open hardware/libsensors/sensors.cpp: open_sensors->sensors_poll_context_t sensors_poll_context_t执行打开每个传感器设备时,遍历/dev/input/目录下的设备文件,以匹配当前需要打开的设备,遍历文件是在 hardware/libsensors/SensorBase.cpp的openInput下实现,如果打开的设备文件不是正在打开的设备文件,会执行下面语句的else部分: if (!strcmp(name, inputName)) { strcpy(input_name, filename); break;

Android 开机启动流程

Android的开机流程 1. 系统引导bootloader 1) 源码:bootable/bootloader/* 2) 说明:加电后,CPU将先执行bootloader程序,此处有三种选择 a) 开机按Camera+Power启动到fastboot,即命令或SD卡烧写模式,不加载内核及文件系统,此处可以进行工厂模式的烧写 b) 开机按Home+Power启动到recovery模式,加载recovery.img,recovery.i mg包含内核,基本的文件系统,用于工程模式的烧写 c) 开机按Power,正常启动系统,加载boot.img,boot.img包含内核,基本文件系统,用于正常启动手机(以下只分析正常启动的情况) 2. 内核kernel 1) 源码:kernel/* 2) 说明:kernel由bootloader加载 3. 文件系统及应用init 1) 源码:system/core/init/* 2) 配置文件:system/rootdir/init.rc, 3) 说明:init是一个由内核启动的用户级进程,它按照init.rc中的设置执行:启动服务(这里的服务指linux底层服务,如adbd提供adb支持,vold提供SD卡挂载等),执行命令和按其中的配置语句执行相应功能 4. 重要的后台程序zygote 1)源码:frameworks/base/cmds/app_main.cpp等 2) 说明:zygote是一个在init.rc中被指定启动的服务,该服务对应的命令是/system/bin/app_process a)建立Java Runtime,建立虚拟机 b) 建立Socket接收ActivityManangerService的请求,用于Fork应用程序 c) 启动System Server 5. 系统服务system server 1)源码:frameworks/base/services/java/com/android/server/SystemServer.jav a 2) 说明:被zygote启动,通过SystemManager管理android的服务(这里的服务指frameworks/base/services下的服务,如卫星定位服务,剪切板服务等) 6. 桌面launcher 1)源码:ActivityManagerService.java为入口,packages/apps/launcher*实现 2) 说明:系统启动成功后SystemServer使用xxx.systemReady()通知各个服务,系统已经就绪,桌面程序Home就是在ActivityManagerService.systemReady()通知的过程中建立的,最终调用()启launcher 7. 解锁 1) 源码: frameworks/policies/base/phone/com/android/internal/policy/impl/*lock* 2) 说明:系统启动成功后SystemServer调用wm.systemReady()通知WindowManagerService,进而调用PhoneWindowManager,最终通过LockPatternKeyguardView显示解锁界面,跟踪代码可以看到解锁界面并不是一个Activity,这是只是向特定层上绘图,其代码了存放在特殊的位置

Apache_Spark源码走读系列篇二

超人学院—Apache Spark源码走读之Task运行期之函数调用关系分析 欢迎转载,转载请注明出处,超人学院。 概要 本篇主要阐述在TaskRunner中执行的task其业务逻辑是如何被调用到的,另外试图讲清楚运行着的task其输入的数据从哪获取,处理 的结果返回到哪里,如何返回。 准备 1.spark已经安装完毕 2.spark运行在local mode或local-cluster mode local-cluster mode local-cluster模式也称为伪分布式,可以使用如下指令运行 MASTER=local[1,2,1024] bin/spark-shell [1,2,1024]分别表示,executor number, core number和内存大小,其中内存大小不应小于默认的512M Driver Programme的初始化过程分析 初始化过程的涉及的主要源文件 1.SparkContext.scala 整个初始化过程的入口 2.SparkEnv.scala 创建BlockManager, MapOutputTrackerMaster, ConnectionManager, CacheManager 3.DAGScheduler.scala 任务提交的入口,即将Job 划分成各个stage的关键 4.TaskSchedulerImpl.scala 决定每个stage可以运行几个task, 每个task分别在哪个executor上运行 5.SchedulerBackend

1.最简单的单机运行模式的话,看LocalBackend.scala 2.如果是集群模式,看源文件 SparkDeploySchedulerBackend 初始化过程步骤详解 步骤1:根据初始化入参生成SparkConf,再根据SparkConf来创建SparkEnv, SparkEnv中主要包含以下关键性组件 1. BlockManager 2. MapOutputTracker 3. ShuffleFetcher 4. ConnectionManager private[spark] val env = SparkEnv.create( conf, "", conf.get("spark.driver.host"), conf.get("spark.driver.port").toInt, isDriver = true, isLocal = isLocal) SparkEnv.set(env) 步骤2:创建TaskScheduler,根据Spark的运行模式来选择相应的SchedulerBackend,同时启动taskscheduler,这一步至为关键 private[spark] var taskScheduler = SparkContext.createTaskScheduler(this, master, appName) taskScheduler.start() TaskScheduler.start目的是启动相应的SchedulerBackend,并启动定时器进行检测 overridedef start() { backend.start() if (!isLocal && conf.getBoolean("spark.speculation", false)) {

基于MT6752的 android 系统启动流程分析报告

基于MT6752的Android系统启动流程分析报告 1、Bootloader引导 (2) 2、Linux内核启动 (23) 3、Android系统启动 (23) 报告人: 日期:2016.09.03

对于Android整个启动过程来说,基本可以划分成三个阶段:Bootloader引导、Linux kernel启动、Android启动。但根据芯片架构和平台的不同,在启动的Bootloader阶段会有所差异。 本文以MTK的MT6752平台为例,分析一下基于该平台的Android系统启动流程。 1、Bootloader引导 1.1、Bootloader基本介绍 BootLoader是在操作系统运行之前运行的一段程序,它可以将系统的软硬件环境带到一个合适状态,为运行操作系统做好准备,目的就是引导linux操作系统及Android框架(framework)。 它的主要功能包括设置处理器和内存的频率、调试信息端口、可引导的存储设备等等。在可执行环境创建好之后,接下来把software装载到内存并执行。除了装载software,一个外部工具也能和bootloader握手(handshake),可指示设备进入不同的操作模式,比如USB下载模式和META模式。就算没有外部工具的握手,通过外部任何组合或是客户自定义按键,bootloader也能够进入这些模式。 由于不同处理器芯片厂商对arm core的封装差异比较大,所以不同的arm处理器,对于上电引导都是由特定处理器芯片厂商自己开发的程序,这个上电引导程序通常比较简单,会初始化硬件,提供下载模式等,然后才会加载通常的bootloader。 下面是几个arm平台的bootloader方案: marvell(pxa935) : bootROM + OBM + BLOB informax(im9815) : bootROM + barbox + U-boot mediatek(mt6517) : bootROM + pre-loader + U-boot broadcom(bcm2157) : bootROM + boot1/boot2 + U-boot 而对MT6752平台,MTK对bootloader引导方案又进行了调整,它将bootloader分为以下两个部分: (1) 第1部分bootloader,是MTK内部(in-house)的pre-loader,这部分依赖平台。 (2) 第2部分bootloader,是LK(little kernel的缩写,作用同常见的u-boot差不多),这部分依赖操作系统,负责引导linux操作系统和Android框架。 1.2、bootloader的工作流程 1.2.1 bootloader正常的启动流程 先来看启动流程图:

基于Spark的机器学习资料43、其它SparkML算法简单介绍

Spark ML算法简单介绍 一、线性回归算法 线性回归(Linear Regression),数理统计中回归分析,用来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,其表达形式为y = w'x+e,e为误差服从均值为0的正态分布,其中只有一个自变量的情况称为简单回归,多个自变量的情况叫多元回归。 这个例子中近简化使用房屋面积一个因子作为自变量,y轴对应其因变量房屋价格。所以我们机器学习的线性回归就变为对于给定有限的数据集,进行一元线性回归,即找到一个一次函数y=y(x) + e,使得y满足当x={2104, 1600, 2400, 1416, 3000, ... }, y={400, 330, 369, 232, 540, ... } 如下图所示: 至于公式的求解,大家可以自己去看一下源码或者方程求解,这里就不讲解了。 二、逻辑回归算法 logistic回归本质上是线性回归,只是在特征到结果的映射中加入了一层函数映射,即先把特征线性求和,然后使用函数g(z)将最为假设函数来预测。g(z)可以将连续值映射到0和1上。 它与线性回归的不同点在于:为了将线性回归输出的很大范围的数,例如从负无穷到正无穷,压缩到0和1之间,这样的输出值表达为“可能性”才能说服广大民众。当然了,把大值压缩到这个范围还有个很好的好处,就是可以消除特别冒尖的变量的影响。

三、贝叶斯分类算法 贝叶斯定理 贝叶斯定理解决的是这样一个问题:已知在事件B发生的条件下,事件A的发生概率P(A|B),怎样得到事件A发生的条件下,事件B的发生概率P(B|A)?贝叶斯定理为我们打通了从P(A|B) 到P(B|A) 的道路。 P(B|A) = P(A|B) ×P(B) / P(A) 举例说明,假设已经有了100个email,其中: 垃圾邮件占比60%,即P(Spam) = 0.6 80%的垃圾邮件包含关键字“buy”,即P(Buy|Spam) = 0.8 20%的垃圾邮件不包含关键字“buy” 正常邮件占比40%,即P(NotSpam) = 0.4 10%的正常邮件包含关键字“buy”,即P(Buy|NotSpam) = 0.1 90%的正常邮件不包含关键字“buy” 现在,第101个email 进来了,它包含关键字“buy”,那么它是垃圾邮件的概率P(Spam|Buy) 是多少? P(Spam|Buy) = P(Buy|Spam) ×P(Spam) / P(Buy) P(Buy) = P(Buy|Spam) ×P(Spam) + P(Buy|NotSpam) ×P(NotSpam) P(Spam|Buy) = (0.8 ×0.6) / (0.8 ×0.6 + 0.1 ×0.4) = 0.48 / 0.52 = 0.923 由此得出,这个email 有92.3%的可能是一个垃圾邮件。 四、SVM支持向量机算法 支持向量机是一个类分类器,它能够将不同类的样本在样本空间中践行分割,其中生成的分隔面叫作分隔超平面。给定一些标记好的训练样本,SVM算法输出一个最优化的分隔超平面。 五、决策树算法 决策树就是通过一系列规则对数据进行分类的一种算法,可以分为分类树和回归树两类,分类树处理离散变量的,回归树是处理连续变量。 样本一般都有很多个特征,有的特征对分类起很大的作用,有的特征对分类作用很小,甚至没有作用。如决定是否对一个人贷款是,这个人的信用记录、收入等就是主要的判断依据,而性别、婚姻状况等等就是次要的判断依据。决策树构建的过程,就是根据特征的决定性程度,先使用决定性程度高的特征分类,再使用决定性程度低的特征分类,这样构建出一棵倒立的树,就是我们需要的决策树模型,可以用来对数据进行分类。 决策树学习的过程可以分为三个步骤:1)特征选择,即从众多特征中选择出一个作为当前节点的分类标准; 2)决策树生成,从上到下构建节点;3)剪枝,为了预防和消除过拟合,需要对决策树剪枝。 六、Kmeans聚类算法 聚类(clustering)与分类(classification)的不同之处在于:分类是一种示例式的有监督学习算法,它要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应,很多时候这个条件是不成立的,尤其是面对海量数据的时候;而聚类是一种观察式的无监督学习算法,在聚类之前可以不知道类别甚至不给定类别数量,由算法通过对样本数据的特征进行观察,然后进行相似度或相异度的分析,从而达到“物以类聚”的目的。 七、LDA主题模型算法 隐含狄利克雷分配(LDA,Latent Dirichlet Allocation)是一种主题模型(Topic Model,即从所收集的文档中推测主题)。甚至可以说LDA模型现在已经成为了主题建模中的一个标准,是实践中最成功的主题模型之一。 那么何谓“主题”呢?,就是诸如一篇文章、一段话、一个句子所表达的中心思想。不过从统计模型的角度来说,我们是用一个特定的词频分布来刻画主题的,并认为一篇文章、一段话、一个句子是从一个概率模型中生成的。也就是说在主题模型中,主题表现为一系列相关的单词,是这些单词的条件概率。形象来说,主题就是一个桶,里面装了出现概率较高的单词,这些单词与这个主题有很强的相关性。 LDA可以用来识别大规模文档集(document collection)或语料库(corpus)中潜藏的主题信息。它采用了词

linux内核启动 Android系统启动过程详解

linux内核启动+Android系统启动过程详解 第一部分:汇编部分 Linux启动之 linux-rk3288-tchip/kernel/arch/arm/boot/compressed/ head.S分析这段代码是linux boot后执行的第一个程序,完成的主要工作是解压内核,然后跳转到相关执行地址。这部分代码在做驱动开发时不需要改动,但分析其执行流程对是理解android的第一步 开头有一段宏定义这是gnu arm汇编的宏定义。关于GUN 的汇编和其他编译器,在指令语法上有很大差别,具体可查询相关GUN汇编语法了解 另外此段代码必须不能包括重定位部分。因为这时一开始必须要立即运行的。所谓重定位,比如当编译时某个文件用到外部符号是用动态链接库的方式,那么该文件生成的目标文件将包含重定位信息,在加载时需要重定位该符号,否则执行时将因找不到地址而出错 #ifdef DEBUG//开始是调试用,主要是一些打印输出函数,不用关心 #if defined(CONFIG_DEBUG_ICEDCC)

……具体代码略 #endif 宏定义结束之后定义了一个段, .section ".start", #alloc, #execinstr 这个段的段名是 .start,#alloc表示Section contains allocated data, #execinstr表示Section contains executable instructions. 生成最终映像时,这段代码会放在最开头 .align start: .type start,#function /*.type指定start这个符号是函数类型*/ .rept 8 mov r0, r0 //将此命令重复8次,相当于nop,这里是为中断向量保存空间 .endr b 1f .word 0x016f2818 @ Magic numbers to help the loader

Android开机启动流程样本

Android的开机流程 1. 系统引导bootloader 1) 源码: bootable/bootloader/* 2) 说明: 加电后, CPU将先执行bootloader程序, 此处有三种选择 a) 开机按Camera+Power启动到fastboot, 即命令或SD卡烧写模式, 不加载内核及文件系统, 此处能够进行工厂模式的烧写 b) 开机按Home+Power启动到recovery模式, 加载recovery.img, recovery.img包含内核, 基本的文件系统, 用于工程模式的烧写 c) 开机按Power, 正常启动系统, 加载boot.img, boot.img包含内核, 基本文件系统, 用于正常启动手机( 以下只分析正常启动的情况) 2. 内核kernel 1) 源码: kernel/* 2) 说明: kernel由bootloader加载 3. 文件系统及应用init 1) 源码: system/core/init/* 2) 配置文件: system/rootdir/init.rc, 3) 说明: init是一个由内核启动的用户级进程, 它按照init.rc中的设置执行: 启动服务( 这里的服务指linux底层服务, 如adbd提供adb支持, vold提供SD卡挂载等) , 执行命令和按其中的配置语句执行相应功能 4. 重要的后台程序zygote 1) 源码: frameworks/base/cmds/app_main.cpp等 2) 说明: zygote是一个在init.rc中被指定启动的服务, 该服务对应的命令是/system/bin/app_process

Spark源码学习(4)——Scheduler

Spark源码学习(4)——Scheduler Scheduler的基本过程 用户提交的Job到DAGScheduler后,会封装成ActiveJob,同时启动JobWaiter监听作业的完成情况。同时依据job中RDD的dependency和dependency属性(窄依赖NarrowDependency,宽依赖ShufflerDependecy),DAGScheduler会根据依赖关系的先后产生出不同的stage DAG(result stage, shuffle map stage)。在每一个stage内部,根据stage产生出相应的task,包括ResultTask或是ShuffleMapTask,这些task会根据RDD中partition的数量和分布,产生出一组相应的task,并将其包装为TaskSet提交到TaskScheduler上去。 DAGScheduler DAGScheduler是高层级别的调度器。实现了stage-oriented调度。它计算一个DAG中stage 的工作。并将这些stage输出落地物化。 最终提交stage以taskSet方式提交给TaskScheduler。DAGScheduler需要接收上下层的消息,它也是一个actor。这里主要看看他的一些事件处理。以下是的所处理的事件。 private[scheduler] case class JobSubmitted( jobId: Int, finalRDD: RDD[_], func: (TaskContext, Iterator[_]) => _, partitions: Array[Int], callSite: CallSite, listener: JobListener, properties: Properties = null) extends DAGSchedulerEvent private[scheduler] case class StageCancelled(stageId: Int) extends DAGSchedulerEvent private[scheduler] case class JobCancelled(jobId: Int) extends DAGSchedulerEvent private[scheduler] case class JobGroupCancelled(groupId: String) extends DAGSchedulerEvent private[scheduler] case object AllJobsCancelled extends DAGSchedulerEvent private[scheduler] case class BeginEvent(task: Task[_], taskInfo: TaskInfo) extends DAGSchedulerEvent private[scheduler] case class GettingResultEvent(taskInfo: TaskInfo) extends DAGSchedulerEvent 还有很多,不一一罗列。

Android系统启动过程详解

Android系统启动过程详解 Android系统启动过程 首先Android框架架构图:(来自网上,我觉得这张图看起来很清晰) Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。 启动的过程如下图所示:(图片来自网上,后面有地址)

下面将从Android4.0源码中,和网络达人对此的总结中,对此过程加以学习了解和总结, 以下学习过程中代码片段中均有省略不完整,请参照源码。

一Init进程的启动 init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行, 并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程。 启动过程就是代码init.c中main函数执行过程:system\core\init\init. c 在函数中执行了:文件夹建立,挂载,rc文件解析,属性设置,启动服务,执行动作,socket监听…… 下面看两个重要的过程:rc文件解析和服务启动。 1 rc文件解析 .rc文件是Android使用的初始化脚本文件(System/Core/Init/readm e.txt中有描述: four broad classes of statements which are Actions, Commands, Services, and Options.) 其中Command 就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是linux 命令, 还有一些是android 添加的,如:class_start :启动服务,class_stop :关闭服务,等等。 其中Options是针对Service 的选项的。 系统初始化要触发的动作和要启动的服务及其各自属性都在rc脚本文件中定义。具体看一下启动脚本:\system\core\rootdir\init.rc 在解析rc脚本文件时,将相应的类型放入各自的List中: \system\core\init\Init_parser.c :init_parse_config_file( )存入到 action_queue、action_list、service_list中,解析过程可以看一下parse_config函数,类似状态机形式挺有意思。 这其中包含了服务:adbd、servicemanager、vold、ril-daemon、deb uggerd、surfaceflinger、zygote、media…… 2 服务启动 文件解析完成之后将service放入到service_list中。 文件解析完成之后将service放入到service_list中。 \system\core\init\builtins.c

RK系统启动流程

RK29机型之Android系统启动流程 分类:瑞芯微RK 2012-02-12 14:50 4439人阅读评论(0) 收藏举报/******************************************************************************************** * author:conowen@大钟 * E-mail:conowen@https://www.wendangku.net/doc/cc18956674.html, * https://www.wendangku.net/doc/cc18956674.html,/conowen * 注:本文为原创,仅作为学习交流使用,转载请标明作者及出处。 ********************************************************************************************/ 第一步:系统引导bootloader,即RK29xxLoaderXXX.bin文件 加电后,CPU将先执行 bootloader程序,然后bootloader首先会读寄存器地址base + APP_DATA1的内容,根据这个地址的值决定是否进入recovery模式或者其它模式。bootloader还会读取MISC分区第一块的内容,决定进入recovery模式还是升级基带Baseband Processor(BP)或做其它事情 而上述寄存器与分区的值是有按键触发或者软件触发的。 a) 开机按reset+返回键,系统进入recovery模式,加载recovery.img,recovery.img 包含内核,基本的文件系统,用于工程模式的烧写 b) 开机按Power,正常启动系统,加载boot.img,boot.img包含内核,基本文件系统,用于正常启动机器(以下只分析正常启动的情况) 第二步:启动内核kernel 1) 源码:kernel/* 2) 说明:kernel由bootloader加载 第三步:文件系统(rootfs)及应用初始化(init) 1) 源码:system/core/init/* 2) 配置文件:system/rootdir/init.rc, 3) 说明:init是一个由内核启动的用户级进程,它按照init.rc中的设置执行:启动服务(这里的服务指linux底层服务,如adbd提供adb支持,vold提供SD卡挂载等),执行 命令和按其中的配置语句执行相应功能 第四步:重要的后台程序zygote 1) 源码:frameworks/base/cmds/app_main.cpp等 2) 说明:zygote是一个在init.rc中被指定启动的服务,该服务对应的命令是 /system/bin/app_process a) 建立Java Runtime,建立虚拟机

Android SystemBar启动流程分析

Android SystemBar启动流程分析 SystemBars的服务被start时,最终会调用该类的onNoService()方法。 @Override public void start() { if (DEBUG) Log.d(TAG, "start"); ServiceMonitor mServiceMonitor = new ServiceMonitor(TAG, DEBUG, mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); mServiceMonitor.start(); // will call onNoService if no remote service is found } @Override public void onNoService() { if (DEBUG) Log.d(TAG, "onNoService"); createStatusBarFromConfig(); // fallback to using an in-process implementation } private void createStatusBarFromConfig() { … mStatusBar = (BaseStatusBar) cls.newInstance(); … mStatusBar.start(); } BaseStatusBar是一个抽象类,故调用其子类的PhoneStatusBar的start 函数。 @Override public void start() { … super.start(); … } 子类的start又调用了父类的start public void start() { … createAndAddWindows(); … }

AndroidL系统启动及加载流程分析

Android L系统启动及加载流程分析 1、概述 Android L的启动可以分为几个步骤:Linux内核启动、init进程启动、native系统服务及java系统服务启动、Home启动,主要过程如下图: 图1 整个启动流程跟4.4及之前的版本相差不多,只是有个别不同之处,本文我们主要分析Linux内核启动之后的过程。

2、启动过程分析 2.1 init进程启动 当系统内核加载完成之后,会启动init守护进程,它是内核启动的第一个用户级进程,是Android的一个进程,进程号为1,init进程启动后执行入口函数main(),主要操作为: 图2 AndroidL上将selinux的安全等级提高了,设为了enforcing模式,4.4上是permissive模式。 解析rc脚本文件,即init.rc脚本,该文件是Android初始化脚本,定义了一系列的动作和执行这些动作的时间阶段e aryl-init、init、early-boot、boot、post-fs等阶段。init进程main 函数中会根据这些阶段进行解析执行。AndroidL上为了流程更清晰,增加了charger(充电开机)、ffbm(工厂模式)、以及late-init阶段,实际上这些阶段是对其他阶段的组合执行,比如late-init:

2.2 ServiceManager的启动 servicemanager的启动就是init进程通过init.rc脚本启动的: 源码在frameworks/native/cmds/servicemanager/service_manager.c中,servicemanager是服务管理器,它本身也是一个服务(handle=0),通过binder调用,为native和Java系统服务提供注册和查询服务的,即某个服务启动后,需要将自己注册到servicemanager中,供其他服务或者应用查询使用。AndroidL上servicemanger中在处理注册和查询动作之前添加了selinux安全检测相关的处理。 2.3 SurfaceFinger、MediaServer进程启动 Android4.4以前,surfacefinger的启动根据属性system_init.startsurfaceflinger,决定是通过init.rc启动还是systemserver进程启动,之后的版本包括AndoridL都是通过init.rc启动的: 启动后会向servicemanager进程注册服务中,该服务启动时主要功能是初始化整个显

BOOTCHART ANDROID文档(开机慢)

BootChart在Android中的应用 1简介 Bootchart是一个能对GNU/Linux boot过程进行性能分析并把结果直观化的工具。它在boot过程中搜集资源利用情况及进程信息然后以PNG,SVG或EPS格式来显示结果。BootChart包含数据收集工具和图像产生工具,数据收集工具在原始的BootChart中是独立的shell程序,但在Android中,数据收集工具被集成到了init程序中。 2BootChart使用步骤概述 ?在主机上安装BootChart ?建立有BootChart支持的init文件 ?安装init到系统镜像 ?使能启动时的BootChart功能 ?收集系统产生的数据 ?根据产生的数据生成图表 ?结果分析 以下部分将对这些步骤进行详细描述(环境:Ubuntu9.04,Android1.6)。 3详细说明 ?在主机上安装BootChart $sudo apt-get install bootchart 注:由于BootChart是用Java语言实现,所以要求其所运行的主机安装Java包。 ?创建支持BootChart功能的‘init’文件 Andoid系统中运行的第一个程序是'init',其所在的目录为Andoid文件系统的根目录下(即/)。'init'是一个由内核启动的用户级进程,主要是对系统进行初始化和根据init.rc与init.xxx.rc文件建立几个基本的服务。 创建'init'时对BootChart的数据收集功能是可选的,默认的'init'是不支持BootChart 的数据收集功能的。要想在Andoid中应用BootChart,必须创建支持BootChart数据收集功能的'init'。 $cd~/myandroid $export INIT_BOOTCHART=true #vim system/core/init/Android.mk 20ifeq($(strip$(INIT_BOOTCHART)),true) 21LOCAL_SRC_FILES+=bootchart.c

相关文档
相关文档 最新文档