2020-08-09 ETHERNET、mpp、rootfs、xargs、tftp、交叉工具编译链

Ethernet:以太网

以太网标准
10M(标准)以太网
百兆以太网
千兆以太网
万兆以太网

MPP:media process platform(媒体处理平台)

转自:https://zhuanlan.zhihu.com/p/87672631

海思MPP功能模块、视频缓存池简介:

一、MPP功能模块

1、MPP功能模块(MPP,media process platform,媒体处理平台)

(1)MPP手册:\01.software\board\document_cn目录下的《HiMPP IPC V2.0 媒体处理软件开发参考.pdf》

(2)详见MPP手册的系统概述1.3部分。

以ko和api形式提供,和驱动处于同一层次。

处理流程主要分为视频输入(VI)、视频处理(VPSS)、视频编码(VENC)、视频解码(VDEC)、视频输出(VO)、视频侦测分析(VDA)、音频输入(AI)、音频输出(AO)、音频编码(AENC)、音频解码(ADEC)、区域管理(REGION)等模块。

VI 模块捕获视频图像,可对其做剪切、缩放等处理,并输出多路不同分辨率的图像数据。

解码模块对编码后的视频码流进行解码,并将解析后的图像数据送 VPSS 进行图像处理或直接送 VO 显示。可对H264/MPEG4/MPEG2 格式的视频码流进行解码。

VPSS 模块接收 VI 和解码模块发送过来的图像,可对图像进行去噪、图像增强、锐化等处理,并实现同源输出多路不同分辨率的图像数据用于编码、预览或抓拍。

编码模块接收 VI 捕获并经 VPSS 处理后输出的图像数据,可叠加用户通过 Region模块设置的 OSD(水印信息)图像,然后按不同协议进行编码并输出相应码流。

VDA 模块接收 VI 的输出图像,并进行移动侦测和遮挡侦测,最后输出侦测分析结果。

VO 模块接收 VPSS 处理后的输出图像,可进行播放控制等处理,最后按用户配置的输出协议输出给外围视频设备。

2、使用SI软件,把MPP文件夹倒入,从例子sample_venc.c文件中的SAMPLE_VENC_1080P_CLASSIC函数开始看

PAYLOAD_TYPE_E(传输的格式类型是什么)

PIC_SIZE_E(图像分辨率大小)

VB_CONF_S(视频缓存池)

二、视频缓存池

1、概念

(1)视频缓存池(VB,video buffer),是一段用于暂存视频数据、进行运算的内存。

(2)视频的裁剪、缩放、修正处理等各种操作,本质上是对内存中的数据进行运算。

(2)视频缓存池的内存由MPP来维护。

系统启动时,把整个SDRAM分成2部分:系统部分(由linux kernel来维护管理)和mpp部分(由mpp系统来维护管理)

(4)缓存池的数量,缓存块的数目和大小,可以由用户程序设置好参数,调用MPP的相应API来向MPP申请分配。

2、相关的数据结构和API

VB_CONF_S 结构体

HI_MPI_VB_SetConf API函数

HI_MPI_VB_Init API函数

rootfs:根文件系统

浅谈linux中的根文件系统(rootfs的原理和介绍)

转自:https://blog.csdn.net/LEON1741/article/details/78159754
linux中有一个让很多初学者都不是特别清楚的概念,叫做“根文件系统”。我接触linux前前后后也好几年了,但是对这个问题,至今也不是特别的清楚,至少没法给出一个很全面很到位的解释。于是,今天我们就来理一理这个话题。

一、先交代一下文件系统

在开始讨论根文件系统这个话题之前,我们必首先交代一下文件系统这个概念。毕竟,根文件系统只是文件系统中的一种比较特殊的形式而已。根据伟大的百度百科:

文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。文件系统由三部分组成:文件系统的接口,对对象操作和管理的软件集合,对象及属性。从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。

文件系统的重要性,我想大家都很清楚,不用多说了。这里有一句话,我觉得非常精辟而且到位的点出了文件系统在linux中的重要性:

尽管内核是linux的核心,但文件却是用户与操作系统交互所采用的主要工具。这对linux来说尤其如此,这是因为在UNIX传统中,它使用文件I/O机制管理硬件设备和数据文件。

二、什么是根文件系统

然后来解释一下“根文件系统”这个名词的基本概念。同样引自百度百科的解释:

根文件系统首先是内核启动时所mount的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。

展开来细说就是,根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统,它的特殊之处在于,它是内核启动时所挂载(mount)的第一个文件系统,内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本(如rcS,inittab)和服务加载到内存中去运行。我们要明白文件系统和内核是完全独立的两个部分。在嵌入式中移植的内核下载到开发板上,是没有办法真正的启动Linux操作系统的,会出现无法加载文件系统的错误。

三、根文件系统为什么这么重要

根文件系统之所以在前面加一个”根“,说明它是加载其它文件系统的”根“,那么如果没有这个根,其它的文件系统也就没有办法进行加载的。

根文件系统包含系统启动时所必须的目录和关键性的文件,以及使其他文件系统得以挂载(mount)所必要的文件。例如:

init进程的应用程序必须运行在根文件系统上;

根文件系统提供了根目录“/”;

linux挂载分区时所依赖的信息存放于根文件系统/etc/fstab这个文件中;

shell命令程序必须运行在根文件系统上,譬如ls、cd等命令;

总之:一套linux体系,只有内核本身是不能工作的,必须要rootfs(上的etc目录下的配置文件、/bin /sbin等目录下的shell命令,还有/lib目录下的库文件等···)相配合才能工作。

Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。成功之后可以自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。在 Linux 中将一个文件系统与一个存储设备关联起来的过程称为挂载(mount)。使用 mount 命令将一个文件系统附着到当前文件系统层次结构中(根)。在执行挂装时,要提供文件系统类型、文件系统和一个挂装点。根文件系统被挂载到根目录下“/”上后,在根目录下就有根文件系统的各个目录,文件:/bin /sbin /mnt等,再将其他分区挂接到/mnt目录上,/mnt目录下就有这个分区的各个目录和文件。

四、如何在内核中挂载根文件系统

init/main.c->

 start_kernel()->vfs_caches_init(totalram_pages)–>

   mnt_init()–>

/* sysfs用来记录和展示linux驱动模型,sysfs先于rootfs挂载是为全面展示linux驱动模型做好准备 */

/* mnt_init()调用sysfs_init()注册并挂载sysfs文件系统,然后调用kobject_create_and_add()创建fs目录 */

sysfs_init();

/* init_rootfs()注册rootfs,然后调用init_mount_tree()挂载rootfs */

init_rootfs();

     init_mount_tree();

1、sysfs文件系统目前还没有挂载到rootfs的某个挂载点上,后续init程序会把sysfs挂载到rootfs的sys挂载点上;

2、rootfs是基于内存的文件系统,所有操作都在内存中完成;也没有实际的存储设备,所以不需要设备驱动程序的参与。基于以上原因,linux在启动阶段使用rootfs文件系统,当磁盘驱动程序和磁盘文件系统成功加载后,linux系统会将系统根目录从rootfs切换到磁盘文件系统。

start_kernel

vfs_caches_init

mnt_init

init_rootfs注册rootfs文件系统

init_mount_tree 挂载rootfs文件系统

vfs_kern_mount

mount_fs

type->mount其实是rootfs_mount

mount_nodev

fill_super 其实是ramfs_fill_super

inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);

sb->s_root = d_make_root(inode);

static const struct qstr name = QSTR_INIT(“/”, 1);[1*]

__d_alloc(root_inode->i_sb, &name);

mnt->mnt.mnt_root = root;[2*]

mnt->mnt.mnt_sb = root->d_sb;[3*]

mnt->mnt_mountpoint = mnt->mnt.mnt_root;[4*]

mnt->mnt_parent = mnt;[5*]

root.mnt = mnt;

root.dentry = mnt->mnt_root;

mnt->mnt_flags |= MNT_LOCKED;

set_fs_pwd(current->fs, &root);

set_fs_root(current->fs, &root);

rest_init

kernel_thread(kernel_init, NULL, CLONE_FS);

在执行kernel_init之前,会建立roofs文件系统。

[1*]处设置了根目录的名字为“/”;

[2*]处设置了vfsmount中的root目录;

[3*]处设置了vfsmount中的超级块;

[4*]处设置了vfsmount中的文件挂载点,指向了自己;

[5*]处设置了vfsmount中的父文件系统的vfsmount为自己;

五、根文件系统各个常用目录简介

正常来说,根文件系统至少包括以下目录:

/etc/:存储重要的配置文件。

/bin/:存储常用且开机时必须用到的执行文件。

/sbin/:存储着开机过程中所需的系统执行文件。

/lib/:存储/bin/及/sbin/的执行文件所需的链接库,以及Linux的内核模块。

/dev/:存储设备文件。

注:五大目录必须存储在根文件系统上,缺一不可。

六、顺便说下linux文件系统的常用目录

Linux文件系统中一般有如下几个目录:

/bin目录

该目录下存放所有用户都可以使用的、基本的命令,这些命令在挂接其它文件系统之前就可以使用,所以/bin目录必须和根文件系统在同一个分区中。

/bin目录下常用的命令有:cat,chgrp,chmod,cp,ls,sh,kill,mount,umount,mkdir,mknod,test等,我们在利用Busybox制作根文件系统时,在生成的bin目录下,可以看到一些可执行的文件,也就是可用的一些命令。

/sbin 目录

该目录下存放系统命令,即只有管理员能够使用的命令,系统命令还可以存放在/usr/sbin,/usr/local/sbin目录下,/sbin目录中存放的是基本的系统命令,它们用于启动系统,修复系统等,与/bin目录相似,在挂接其他文件系统之前就可以使用/sbin,所以/sbin目录必须和根文件系统在同一个分区中。

/sbin目录下常用的命令有:shutdown,reboot,fdisk,fsck等,本地用户自己安装的系统命令放在/usr/local/sbin目录下。

/dev目录

该目录下存放的是设备文件,设备文件是Linux中特有的文件类型,在Linux系统下,以文件的方式访问各种设备,即通过读写某个设备文件操作某个具体硬件。比如通过”dev/ttySAC0”文件可以操作串口0,通过”/dev/mtdblock1”可以访问MTD设备的第2个分区。

/etc目录

该目录下存放着各种配置文件,对于PC上的Linux系统,/etc目录下的文件和目录非常多,这些目录文件是可选的,它们依赖于系统中所拥有的应用程序,依赖于这些程序是否需要配置文件。在嵌入式系统中,这些内容可以大为精减。

/lib目录

该目录下存放共享库和可加载(驱动程序),共享库用于启动系统。运行根文件系统中的可执行程序,比如:/bin /sbin 目录下的程序。

/home目录

用户目录,它是可选的,对于每个普通用户,在/home目录下都有一个以用户名命名的子目录,里面存放用户相关的配置文件。

/root目录

根用户的目录,与此对应,普通用户的目录是/home下的某个子目录。

/usr目录

/usr目录的内容可以存在另一个分区中,在系统启动后再挂接到根文件系统中的/usr目录下。里面存放的是共享、只读的程序和数据,这表明/usr目录下的内容可以在多个主机间共享,这些主要也符合FHS标准的。/usr中的文件应该是只读的,其他主机相关的,可变的文件应该保存在其他目录下,比如/var。/usr目录在嵌入式中可以精减。

/var目录

与/usr目录相反,/var目录中存放可变的数据,比如spool目录(mail,news),log文件,临时文件。

/proc目录

这是一个空目录,常作为proc文件系统的挂接点,proc文件系统是个虚拟的文件系统,它没有实际的存储设备,里面的目录,文件都是由内核临时生成的,用来表示系统的运行状态,也可以操作其中的文件控制系统。

/mnt目录

用于临时挂载某个文件系统的挂接点,通常是空目录,也可以在里面创建一引起空的子目录,比如/mnt/cdram /mnt/hda1 。用来临时挂载光盘、硬盘。

/tmp目录

用于存放临时文件,通常是空目录,一些需要生成临时文件的程序用到的/tmp目录下,所以/tmp目录必须存在并可以访问。


xargs:Linux xargs命令

xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。它把一个数据流分割为一些足够小的块,以方便过滤器和命令进行处理。通常情况下,xargs从管道或者stdin中读取数据,但是它也能够从文件的输出中读取数据。xargs的默认命令是echo,这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。

xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令,下面是一些如何有效使用xargs 的实用例子。

1. 当你尝试用rm 删除太多的文件,你可能得到一个错误信息:/bin/rm Argument list too long. 用xargs 去避免这个问题

find ~ -name ‘*.log’ -print0 | xargs -0 rm -f

2. 获得/etc/ 下所有*.conf 结尾的文件列表,有几种不同的方法能得到相同的结果,下面的例子仅仅是示范怎么使用xargs ,在这个例子中实用 xargs将find 命令的输出传递给ls -l

# find /etc -name "*.conf" | xargs ls –l

3. 假如你有一个文件包含了很多你希望下载的URL, 你能够使用xargs 下载所有链接

# cat url-list.txt | xargs wget –c

4. 查找所有的jpg 文件,并且压缩它

# find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz

5. 拷贝所有的图片文件到一个外部的硬盘驱动

# ls *.jpg | xargs -n1 -i cp {} /external-hard-drive/directory

EXAMPLES

find /tmp -name core -type f -print | xargs /bin/rm -f

Find files named core in or below the directory /tmp and delete them.  Note that this will work incorrectly if there are any filenames containing newlines or spaces.

find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f

Find  files  named core in or below the directory /tmp and delete them, processing filenames in such a way that file or directory names containing spaces or newlines are correctly handled.

find /tmp -depth -name core -type f -delete

Find files named core in or below the directory /tmp and delete them, but more efficiently than in the previous example (because we avoid the need to use fork(2) and exec(2) to launch rm and we don't need the extra xargs process).

cut -d: -f1 < /etc/passwd | sort | xargs echo

Generates a compact listing of all the users on the system.

xargs sh -c 'emacs "$@" < /dev/tty' emacs

Launches the minimum number of copies of Emacs needed, one after the other, to edit the files listed on xargs' standard input.  This example achieves the same effect as BSD's -o option, but in a more flexible and portable way.


TFTP

【转】TFTP 详解

转自:https://blog.csdn.net/young2415/article/details/91125718

文章目录

概述

建立连接

下载

上传

错误机制

代码实现

实验环境

实验过程

延伸

概述

TFTP,全称是 Trivial File Transfer Protocol(简单文件传输协议),基于 UDP 实现,该协议简单到只能从远程服务器读取数据或向远程服务器上传数据。TFTP 有三种模式:netascii,这是8位的ASCII码形式;另一种是octet,这是8位源数据类型;最后一种 mail 已经不再支持,它将返回的数据直接返回给用户而不是保存为文件。

虽然 TFTP 不具备通常的 FTP 的许多功能,但是学习 TFTP 可以帮助我们了解网络通信协议的基本工作过程和原理,对后续学习更加复杂的协议有很大的帮助作用。

首先看一下 TFTP 的包的类型,TFTP 有 5 种类型的包:

建立连接

默认情况下,作为 TFTP 服务器的主机 A 会监听 69 端口,当作为客户端的主机 B 想要下载或上传文件时,会向主机 A 的 69 端口发送包含读文件(下载)请求或写文件(上传)请求的数据包。主机 A 收到读写请求后,会打开另外一个随机的端口,通过这个端口向主机 B 发送确认包、数据包或者错误包。

下载

客户端向服务器的 69 端口(通常情况下)发送一个读请求,服务器收到这个读请求以后,会打开另外一个随机的端口(假设端口号是 59509),然后在它默认的路径下寻找这个文件,找到这个文件以后,每次读入文件的 512 个字节,通过端口 59509 将这 512 个字节放入数据包中发送给客户端,数据包中还包含了操作码和数据块的编号,块编号从 1 开始计数;客户端收到数据包以后,会向服务器的 59509 端口发送一个确认包,里面包含了它收到的数据包的块编号;服务器收到确认包以后,继续发送文件的下一个 512 个字节。

如此循环往复,直到文件的末尾,最后一个数据包的数据块的大小会小于 512 个字节,这时服务器就认为传输已经结束,等他接收到这最后一个数据包的确认包之后就会主动关闭连接。而客户端收到这个小于 512 个字节的数据包后也认为传输已经结束,发送完确认包之后也会关闭连接。

也许会有一种极端情况,就是文件的大小正好是 512 字节的倍数,这样的话,最后一个数据包的大小也是 512 个字节,这时服务器发送完包含文件数据的数据包以后,还会额外发送一个包含 0 字节的数据包,作为最后一个数据包,这样就可以保证客户端收到的最后一个数据包的大小总是小于 512 个字节的。也就是说,对于客户端而言,只要它收到的数据包的大小小于 512 个字节,它就认为传输已经结束,它就会关闭连接。

下面是 TFTP 下载图示:

上传

客户端向服务器的 69 端口(通常情况下)发送一个写请求,服务器收到这个写请求以后,会打开另外一个随机的端口(假设端口号是 59509),向客户端发送一个确认包,其中块编号是 0,以此来告诉客户端自己已经准备好接收文件,并且告诉客户端自己接收文件的端口号。

然后客户端就开始向服务器的 59509 端口发送数据包,服务器收到数据包后向客户端发送确认包,直到整个文件发送完毕。这个过程和下载是一样的,只不过双方的角色互换了,客户端成了发数据的一方,而服务器是接收数据的一方。

下面是 TFTP 上传图示:

错误机制

TFTP 提供了一些错误机制,若出现错误,服务器会向客户端发送 ERROR 包,包格式如下:

前两个字节是操作码,值是 5,代表这是一个 ERROR 包。接下来两个字节是差错码,代表了错误的类型,下面是不同的差错码对应的错误类型:

差错码含义

1File not found. (文件未找到,服务器未找到下载请求中指定的文件)

2Access violation. (访问违规,程序对于服务器的默认路径没有写权限导致的)

3Disk full or allocation exceeded. (磁盘已满或超出分配,上传文件时可能会出现这个错误)

4Illegal TFTP operation. (非法的 TFTP 操作,服务器无法识别 TFTP 包中的操作码)

5Unknown transfer ID. (未知的传输标识)

6File already exists. (文件已存在,要上传的文件已存在于服务器中)

7No such user. (没有该用户)

接下来的 n 个字节用于存放错误信息,这部分可以由程序员自己决定存放什么信息。最后一个字节是 0,用来标识结尾。

代码实现

下面以下载文件为例,用 Python 实现一个 TFTP 的客户端。

实验环境

Windows 10

VMware 15,里面安装了 Windows 10 操作系统的虚拟机

Python 3.7

tftpd64(一个支持 TFTP 协议的软件,安装到 Windows 10 虚拟机里面作为服务器)

下面是 Python 代码:

#filename: tftp_client_download.py

import struct

from socket import *

···

第一个参数是要下载的文件名,类型是字符串

第二个参数是服务器的IP地址和端口号,类型是元组,

元组中有两个元素,第一个元素是IP地址,类型是字符串,第二个元素是端口号,类型是整数。

比如:('192.168.1.2', 69)

···

def download(file_name, servAddr):

    file_name_byte_array = file_name.encode('gb2312')

    #组包,octet 代表TFTP协议的一种模式

    sendData = struct.pack('!H'+str(len(file_name_byte_array))+'sb5sb',

                          1, file_name_byte_array, 0, b'octet', 0)

    udpSocket = socket(AF_INET, SOCK_DGRAM)

    udpSocket.sendto(sendData, servAddr)

    newFile = open(file_name, 'wb')

    while True:

        #等待接收数据

        recvInfo = udpSocket.recvfrom(1024) #1024表示本次接受的最大字节数

        transPort = recvInfo[1][1] #传输端口

        data = recvInfo[0] #TFTP数据包的字节流

        len_data = len(data)

        result = struct.unpack("!H", data[:2]) #解包

        opcode = result[0] #获取操作码

        if opcode == 3: #如果操作码是3,说明是DATA包

            result = struct.unpack('!H'+str(len_data-4)+'s', data[2:len_data])

            block = result[0] #获取块编号

            fileStream = result[1] #文件字节流

            newFile.write(fileStream)

            #向服务器发送一个确认包

            ackInfo = struct.pack('!HH', 4, block)

            udpSocket.sendto(ackInfo, (servAddr[0], transPort))

            if len(fileStream) < 512:

                break

        elif opcode == 5: #如果操作码是5,说明是ERROR包

            result = struct.unpack('!H'+str(len_data-5)+'s', data[2:len_data-1])

            print('传输出现异常!')

            print(result[1].decode('gb2312')) #输出错误信息

            break

    newFile.close()

    udpSocket.close()

def main():

    #服务器的IP地址

    serverIP = '192.168.133.135'

    #服务器监听端口,默认是69,这只是用来监听客户端请求的端口,另外还有操作系统随机分配的用来传输文件的端口

    serverPort = 69

    servAddr = (serverIP, serverPort)

    filename = 'zoro.png'

    download(filename, servAddr)


if __name__ == '__main__':

    main()

实验过程

在虚拟机中打开 tftpd64,选择 Tftp Server 选项卡,点击右上角的 Browse 按钮,选择一个主目录,将来收到下载请求的时候,程序会在你选择的这个目录里查找请求下载的文件。

查看一下虚拟机的IP地址,将上面 Python 代码中的服务器 IP 地址改成虚拟机的IP地址,在真实的电脑中运行 Python 代码。

如图所示,若没有出现任何错误提示,就文件说明下载成功,文件已经下载到了当前目录下。

延伸

在代码运行过程中,还可以打开 Wireshark,抓取 TFTP 包,查看其具体内容。


交叉工具编译链

【转】交叉编译和交叉工具链

转自:https://www.cnblogs.com/fengliu-/p/10126826.html

一、交叉编译简介

1、什么是交叉编译

1.1 本地编译

        解释什么是交叉编译之前,先要明白一个概念:本地编译

       我们之前常见的软件开发,都是属于本地编译:在当前的PC下,x86的CPU下,直接编译出来程序,可以运行的程序(或者库文件),其可以直接在当前的环境,即x86的CPU下,当前电脑中,运行。

      此时的编译,可以叫做,本地编译,即在当前目标平台下,编译出来的程序,也只是放到当前平台下,就可以运行的。

2.2 交叉编译

       交叉编译,是一个和,本地编译,相对应的概念。

       而所谓的,交叉编译,就是:在一种平台上编译,编译出来的程序,是放到别的平台上运行即编译的环境,和运行的环境不一样,属于交叉的,此所谓cross。

        交叉编译,这个概念,主要和嵌入式开发有关。

例 1.1. 在x86平台上编译,在ARM平台上运行

一种最常见的例子就是:

在进行嵌入式开发时

手上有个嵌入式开发板,CPU是arm的

然后在x86的平台下开发,比如Ubuntu的Linux,或者是Win7

然后就需要:

在x86的平台上,(用交叉编译器)去编译你写好的程序代码

编译生成的(可执行的)程序,是放到目标开发板,arm的CPU上运行的

此所谓:在x86平台上编译,在ARM平台上运行

交叉编译,英文常写作cross compile,也有其他写法:crosscompile, cross compiling等


2、为何要有交叉编译

       之所以要有交叉编译,主要原因是:嵌入式系统中的资源太少

       具体的解释就是:交叉编译出来的程序,所要运行的目标环境中,各种资源,都相对有限,所以很难进行直接的本地编译

       最常见的情况是:在进行嵌入式开发时,目标平台,即嵌入式开发板,比如是最大主频200MHz的ARM的CPU,加上32M的RAM,加上1G的Nand Flash等等。在如此相对比较紧张的硬件资源的前提下,在已经运行了嵌入式Linux的前提下,是没法很方便的直接在嵌入式Linux下,去本地编译,去在ARM的CPU下,编译出来,供ARM的CPU可以运行的程序的。因为编译,开发,都需要相对比较多的CPU,内存,硬盘等资源,而嵌入式开发上的那点资源,只够嵌入式(Linux)系统运行的,没太多剩余的资源,供你本地编译。

BusyBox中包含make等和编译开发相关的工具

对应的,等你后期熟悉了嵌入式开发,熟悉了Busybox后,

比如在Buildroot中去配置Busybox,或者单独交叉编译BusyBox时:

【记录】Ubuntu下为QEMU的arm平台交叉编译BusyBox

就会看到,后来的BusyBox,功能增加后,也已经包含了一些,和编译开发相关的工具,比如make等等

而这些工具,本来的话,只是,放在PC端使用,即在x86平台下做开发的时候,在交叉编译的时候,才用到的工具,

现在,也在(BusyBox的)嵌入式环境中,支持了。

此时,如果,你在BusyBox中把相关的开发工具都选上的话,

再加上,你的目标开发板的硬件配置足够强大的话,比如CPU都是以GHz为单位,等等

加上相关的开发的库和工具都很全的话

实际上,至少理论上,也是可以在你的嵌入式Linux中,进行,有限的,甚至是很大程度上的,本地开发

即,直接在ARM的开发板上,嵌入式Linux中,直接进行嵌入式开发,进行针对ARM的本地编译

比如,编译出一个helloworld,估计还是可以的

这样,就不存在,或者说,避免了,此处所说的,交叉编译,而变成了本地编译

就相当于,之前在x86的PC端的,编译程序放在x86的CPU上运行的本地编译,

在ARM的CPU,嵌入式Linux中,也实现了

但是很明显,对于更加复杂的程序或者库,在ARM开发板上直接编译的可行性和效率,相对就很低

而且如果是本身折腾Uboot等东西,本身目标运行环境,就没有完整的(嵌入式Linux)系统的话,那么就更加没法在目标平台实现本地编译了。

则还是只能进行,此处所说的,交叉编译

二、交叉工具链简介

1、什么是工具链

所谓的工具链,两部分的含义:

a -- 工具

       工具,即tool

       工具,是用来干活的;此处要干的活,目标是为了:生成(可以运行的)程序或库文件

而为了达成此目标,内部的执行过程和逻辑主要包含了:

1)、编译

        编译的输入(对象)是:程序代码

        编译输出(目标)是:目标文件

        编译所需要的工具是:编译器

        编译器,常见的编译器,即为gcc

2)、链接

        链接的输入(对象)是:(程序运行时所依赖的,或者某个库所依赖的另外一个)库(文件)

        链接的输出(目标)是:程序的可执行文件,或者是可以被别人调用的完整的库文件

        链接所需要的工具是:链接器

        链接器,即ld

        即,此处,为了将程序代码,编译成可执行文件,涉及到编译,链接(等其他步骤),要依赖到很多相关的工具,最核心的是编译器gcc,链接器ld。而此处,所谓的工具,主要指的就是:和程序编译链接等相关的gcc,ld等工具

binutils包含了ld等工具

实际上,上面所说的ld,只是处理操作目标文件,二进制文件的最主要的一个工具

而和操作目标等文件相关的,还有其他很多工具的:as,objcopy,strip,ar等等工具的

所以,对此,GNU官网,弄出一个binutils,即binary utils,二进制工具(包),集成了这些,和操作二进制相关的工具集合,叫做binutils

所以,之后你所见到的,常见的工具,就是那个著名的GNU Binutils了。

b -- 链

       链,即链条,chain

       之所以能称为链,说明不止一个东西,然后,按照对应的逻辑,串在一起,链在一起。而对应的,涉及到的:

不止一个东西:指的就是前面所说的那个工具,即:和程序编译链接等相关的gcc,binutils等工具

按照对应的逻辑:指的就是,按照程序本身编译链接的先后顺序,即:先编译,后链接,再进行后期其他的处理等等,比如用objcopy去操作相应的目标文件等等。

      如此的,将:

      和程序编译链接等相关的gcc,binutils等工具按照先编译后链接等相关的编译程序的内在逻辑串起来,就成了我们所说的:工具链


2、什么是交叉工具链

       普通所说的,工具链指的是当前自己的本地平台的工具链。

       用于交叉编译的工具链,就叫做交叉工具链。即那些工具,即编译的gcc,链接的ld,以及相关的工具,用于交叉编译的,工具链,叫做交叉工具链。

       交叉工具链,很明显,是用来,交叉编译,跨平台的程序所用的。交叉工具链,和(本地)工具链类似,也是包含了很多的,对应的工具,交叉编译版本的gcc,ld,as等等。但是,由于其中最最主要的是用于编译的gcc,所以,我们也常把:交叉工具链,简称为交叉编译器

       即严格意义上来说,交叉编译器,只是指的是交叉编译版本的gcc。但是实际上为了叫法上的方便,我们常说的交叉编译器,都是指的是交叉工具链。常说的交叉编译版本的gcc,比如arm-linux-gcc,实际上指代了,包含一系列交叉编译版本的交叉工具链(arm-linux-gcc,arm-linux-ld,arm-linux-as等等)而此文中,后面,所说的,如无特殊指明,均用交叉编译器指代交叉工具链。


总结:

       交叉编译就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,比如在PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平台上的程序,编译得到的程序在X86 CPU平台上是不能运行的,必须放到ARM CPU平台上才能运行,虽然两个平台用的都是Linux系统。 交叉编译工具链是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils、gcc和glibc三个部分组成。有时出于减小 libc 库大小的考虑,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351