您的位置:首页 > 其它

poky:单个任务是如何被执行的

2011-11-02 15:11 183 查看
* 范围

本文忽略了任务的依赖及其他处理,仅讨论单个任务是如何被执行的。

* 简介:

任务是定义在bb文件中的python/shell函数,代表了软件包build过程中的一个步骤。Bitbake约定,任务名必须以’do_‘开

始,bitbake提供任务的分析和处理机制,具体的任务由bbclass/bbfile提供。

* 前情提要:

Bitbake以Server/UI的方式运行,Server端负责等待并执行命令,UI端负责提交命令并回显结果,二者通过一个双向命令管道

和一个状态队列进行交互。Server决定何时执行什么命令,而命令的具体执行由Cooker负责,这种机制通过回调函数实现。

以bzip2为例,执行以下命令时:



$ bitbake bzip2

1)Bitbake分析命令行得到:cmdline={'action': ['buildTargets', ['bzip2'], 'build'], 'msg': None};

2)UI调用server.runCommand(cmdline['action']),把命令传递给Server;

3)Server交给cooker处理,cooker.buildTargets()被执行,它把自己定义的方法buildTargetsIdle()注册到Server的_idlefunctions列表;

4)Server轮询并执行异步命令,控制权交还给buildTargetsIdle(),故事从这里开始了...

* 任务执行:

Bitbake中任务是一个对象,任务的表现形式是TaskData实例。TaskData可以添加,删除任务,处理任务的各种依赖,但是不能执行任务。

任务的执行依靠RunQueue实现, RunQueue是一个状态机,根据当前所处状态执行相应的操作,RunQueue初始化时状态为”runQueueSceneInit“。

从buildTargetsIdle()开始分析, '->'表示函数/方法的调用关系:

-> rq.execute_runqueue():

该方法执行runqueue队列中的任务,在初始状态下,它调用的是RunQueueExecuteScenequeue实例的execute()方法:

945 self.rqexe = RunQueueExecuteScenequeue(self)

948 retval = self.rqexe.execute()

-> RunQueueExecuteScenequeue.execute()

运行队列中的任务,每一个任务都不是单独存在的,若干任务构成了一条任务链,每个可执行任务最终要通过以下方式被执行:

1602 pid, pipein, pipeout = self.fork_off_task(fn, realtask, taskname)

-> RunQueueExecuteScenequeue.fork_off_task(): 这是一个Wrapper,下面才是真正的fork_off_task()

-> RunQueueExecute.fork_off_task():

先检查和设置任务执行的环境和相关变量,任务的Flag:[umask/fakeroot]就是在这里处理的; 执行任务调用如下方法:

1160 bb.build.exec_task

-> bb.build._exec_task(): 执行任务要比单独执行一个函数复杂一些,仍然需要处理任务相关的环境变量和数据;然后剥去任务的外衣,把它当做函数处理:

321 exec_func(task, localdata)

-> bb.build.exec_func(): 处理任务的其他Flags,根据任务类型(python/shell)分而治之;

170 if ispython:

171 exec_func_python(func, d, runfile, cwd=adir)

172 else:

173 exec_func_shell(func, d, runfile, cwd=adir)

a. -> bb.build.exec_func_python(): 如果任务是python函数:

200 utils.better_exec(comp, {"d": d}, code, bbfile)

-> bb.utils.better_exec(): python类型的任务最终由python内置函数exec执行:

343 exec(code, _context, context)

b. -> bb.build.exec_func_shell():如果任务是shell函数:

243 bb.process.run(cmd, shell=False, stdin=NULL, log=logfile)

-> bb.process.run():把函数转换成命令并返回命令的输出:

95 pipe = Popen(cmd, **options) # subprocess.Popen(), 有关Popen()详细使用请参考subprocess模块的help信息。

至此一个任务执行完毕。

* 总结:

Bitbake中用TakeDate,RunQueueData组织任务数据,而且任务处理过程中还涉及到了数据缓存,日志和事件信息的处理,它们

在BB中被抽象成了不同的类型和对象,希望以后能逐步分析,最终形成一个完整的BB对象类型系统说明。

* 参考:

$ bitbake bzip2 # 部分输出

NOTE: Resolving any missing task queue dependencies

NOTE: Preparing runqueue

NOTE: Executing SetScene Tasks

NOTE: Running setscene task 97 of 277 (/home/wenzong/sdb2/poky/meta/recipes-extended/bzip2/bzip2_1.0.6.bb:do_populate_sysroot_setscene)

NOTE: package bzip2-1.0.6-r3: task do_populate_sysroot_setscene: Started

NOTE: package bzip2-1.0.6-r3: task do_populate_sysroot_setscene: Succeeded

....

* Task Flags:

[dirs]: 任务运行前创建的目录;

[cleandirs]: 任务运行前创建,并且是空目录;

[noexec]: 不需要执行的任务;

[nostamp]: 不生成stamp文件,任务总是被重新执行;

[fakeroot]: 任务需要在fakeroot环境下执行;

[umask]: 任务运行时的umask

[depends/deptask/rdeptask/recdeptask/recrdeptask]: 依赖的任务必须完成才能执行此任务
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: