LXC简介
LXC即Linux Container,是利用Linux内核容器特性为用户提供空间接口的开源工具,用户可以通过其提供的API创建和管理系统或者应用程序容器。LXC利用内核支持的资源隔离以及控制机制,通过对容器的配置,使用一系列工具对容器进行控制,可以快速部署,具有较小的虚拟化开销的优点。
LXC功能的实现主要依赖Linux内核的命名空间(Namespace)资源隔离机制和控制群(Cgroup)资源控制机制。命名空间将LXC启动的进程隔离放入独立的Namespace,形成独立的一组进程视图。同时Cgroup机制负责不同系统的资源的配置,分配CPU节点和Memory节点,以及监控容器空间内系统的运行状况。这样在容器空间内的进程只能感受到当前容器的状况。Cgroup可以为不同用户层面的资源管理,提供一个统一化的接口。从单个进程的资源控制到操作系统层面,Cgroup主要提供三个主要功能。一是资源限制,对进程组使用的资源总额进行限制。二是优先级分配,通过分配CPU时间片数量及硬盘IO带宽大小,实际上就相当于控制进程的优先级。三是资源统计,可以统计系统的资源使用量,如CPU使用时长、内存使用量等。一般地,LXC机制的系统架构图大致如下。多套不同类型的OS可运行在同一套硬件上,除了宿主OS以外其它OS均运行在LXC虚拟出的容器空间。
车载系统往往存在多屏显示的需求,例如传统上车辆的中控屏显和仪表系统各自运行在独立的SOC硬件上,多套屏显就要对应多套硬件设备。随着汽车电子化的发展,车载传感器数量越来越多,汽车整体能耗和线路复杂性也随之增加,同时汽车行业的竞争越来越激烈,各车厂各车型越来越利薄,因此车企在智能驾驶舱的屏显方案中,降低硬件成本成为他们重点考虑的方面之一。例如信大捷安提出的智能座舱LXC容器化安全系统方案,就是一种“单硬件-多系统-多屏幕”的车载系统解决方案,同时满足仪表盘、IVI系统屏、副驾屏、HUD屏等的显示。
LXC源码编译
LXC项目的网站地址是https://linuxcontainers.org/,该站点给出了LXC项目的介绍、LXC工具的操作说明、相关API的使用方法、相关文章和论坛以及源码的下载方法等。源码在github上的地址是https://github.com/lxc/lxc,目前有9个稳定版本(stable-0.7.4 ~ stable-6.0)的源码可供使用,不同版本对Linux内核的要求以及编译方法略有不同,我们这里使用的是stable-1.0版本,它要求内核版本大于2.6.32,要求使用glibc或musl库,支持arm64架构,我们使用的开发板设备满足这些要求。源码stable-1.0的原始目录结构如下。其中src/lxc目录存放了LXC功能实现的核心代码,autogen.sh是编译的入口脚本。
利用开发板交叉工具编译链环境编译源码,首先执行“./autogen.sh”,这个脚本根据configure.ac文件的配置项生成了configure文件,这个文件包含几个主要的配置变量,变量“prefix”指将来生成的LXC编译产物存放路径,“host”指宿主系统所在硬件的架构,“target”指LXC运行的目标架构,通常和“host”一致,“build”指编译LXC的环境架构,我们是在Ubuntu中编译的。运行configure,然后会进行一系列的环境check,最后生成Makefile。执行“make”进入编译阶段,完成后再执行“make install”将编译产物打包到configure指定的目录。在编译过程中遇到过多项编译错误(这里没有展示),优化修改代码后编译通过。编译产物打包完成如下。
目录bin存放LXC一系列重要进程,主要用于控制容器的行为,如lxc-checkconfig用于检查当前环境是否支持LXC功能,lxc-create用于创建容器,lxc-start用于启动一个已创建的容器,lxc-attach用于开启容器的shell或在容器中运行应用程序,lxc-info用于查看容器的运行情况,lxc-stop用于终止容器运行,lxc-destroy用于将已创建的容器从系统中删除。这些进程的详细用法见地址https://linuxcontainers.org/lxc/manpages/。
目录etc/lxc存放了容器的默认配置文件default.conf,这里只给出了配置容器的网络连接类型、端口及MAC地址的样例,如果不改动,则用lxc-create创建出来的容器的配置文件就是default.conf的内容。我们可以自己在default.conf中修改或添加其它配置项,LXC规定的配置项可在源码src/lxc/confile.c中查找。
目录lib存放了核心库文件liblxc.so。目录var/lib/lxc当前为空,将来要存放所创建的容器的配置文件。
适配开发板设备
适配过程
LXC功能的实现依赖Linux内核Namespace和Cgroup机制,需要打开相关的内核配置开关,添加的内核编译选项如下。重新编译内核镜像。
将前面的LXC编译产物目录workdir打包放到开发板的指定位置。首先检查环境是否支持运行LXC,执行lxc-checkconfig结果如下,发现Cgroup namespace这项后面是红色的required,说明当前环境不完善。
原因在于并未进行Cgroup节点挂载,创建一个目录/cgroup作为Cgroup挂载目录,然后执行“mount -t cgroup cgroup /cgroup”,再检查环境如下,是正常的,应该可以运行LXC了。
尝试创建一个容器,运行lxc-create,-n后面是容器名称,-t后面是模板名称,LXC项目提供了多种适配不同体系的容器模板如ubuntu、debian、aarch64等,这里我们不采用模板。
在workdir的目录var/lib/lxc出现了名为fym_ct的目录,这就是刚才创建的名为fym_ct的容器的配置文件目录,里面有个config文件。
查看config内容如下,这几行就是前面提到的etc/lxc/default.conf的内容,即我们创建的fym_ct就是按照默认配置生成的。
实际的网口并不是lxcbr0,修改成开发板上的br-lan。运行容器还需要指定待运行的rootfs,这里我们就使用开发板自身的rootfs。为了与host名称区分,给容器添加一个自身的uts名称。修改后的config如下。
运行lxc-info查看当前新建容器fym_ct的状态,显示STOPPED,未运行。
运行lxc-start启动该容器,命令的后面/sbin/procd表示rootfs的启动进程路径,因为开发板的init进程就是/sbin/procd。执行后可以看到系统启动的相关日志打印如下。
此时查看fym_ct状态如下,看到State已经变成了RUNNING,PID为8891,这个就是由lxc-start启动的fym_ct中的init进程即/sbin/procd的进程号,区别于host的/sbin/procd进程号(PID为1)。IP为192.168.0.1,这个就是我们前面指定的br-lan的IP地址。Link后的vethO420PI是系统随机给出的虚拟网卡名称。
我们可以进入fym_ct的shell中,运行lxc-attach,可以看到打印了built-in shell,用户名称从host的OpenWrt变成了fym_ct,相当于进入了fym_ct中运行的另一个rootfs系统内部。
进入后发现/proc目录为空,先执行/proc挂载。
查看进程信息,对照在host中查看到的进程信息,可以看到host中的PID8891在fym_ct中进程号为1,同一个进程的PID在host中是按host的/sbin/procd进程号增加的,而在fym_ct中是从进程号1增加的,类似于在另一块设备上启动了开发板的rootfs。
资源占用情况
在运行容器fym_ct之前,查看系统的内存情况如下,占用83MB。
启动fym_ct之后,系统内存情况如下,占用114MB,可以看到fym_ct运行起来后系统内存的占用增加了31MB。
此时再创建一个新的容器fym_ct2,仍然在其中运行开发板的rootfs,待其进程都启动后,查看系统内存情况如下,占用140MB。可以看到运行了fym_ct2后系统内存占用又增加了26MB。
运行容器之前,查看系统的CPU使用率情况如下,用户与系统加起来的占用率约36%。
启动fym_ct之后,系统的CPU使用率情况如下,用户与系统加起来占用率约为43%,增加了约7%。
再启动fym_ct2之后,系统的CPU使用率情况如下,用户与系统加起来占用率约为48%,再增加了约5%。
资源使用情况可总结如下表。
系统配置 | Memory / MB | Memory diff / MB | CPU / % | CPU diff / % |
---|---|---|---|---|
Host rootfs | 83 | / | 36 | / |
Host rootfs + Container fym_ct(运行开发板rootfs) | 114 | +31 | 43 | +7 |
Host rootfs + Container fym_ct(运行开发板rootfs) + Container fym_ct2(运行开发板rootfs) | 140 | +57 | 48 | +12 |
参考资料
[1] https://linuxcontainers.org/
[2] https://www.jianshu.com/p/e8f5d92b711f
[3] https://blog.youkuaiyun.com/omnispace/article/details/116358355
作者声明
欢迎关注微信公众号“21号研究室”,交流更多有关嵌入式软件的知识和信息,一起成长进步。