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

* 范围

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

* 简介:
任务是定义在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]: 依赖的任务必须完成才能执行此任务
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值