附录B 其他第三方软件移植(FTP、OpenSSH、GDB)

目录

  • 开发板 FTP 服务器移植与搭建
    • vsftpd 源码下载
    • vsftpd 移植
    • vsftpd 服务器测试
      • 配置vsftpd
      • 添加新用户
      • Filezilla 连接测试
  • 开发板 OpenSSH 移植与使用
    • OpenSSH 简介
    • OpenSSH 移植
      • OpenSSH 源码获取
      • 移植zlib 库
      • 移植openssl 库
      • 移植openssh 库
    • openssh 设置
    • openssh 使用
      • ssh 登录
      • scp 命令拷贝文件
  • 嵌入式GDB 调试搭建与使用
    • GDB 简介
    • GDB 移植
      • 获取gdb 和gdbserver 源码
      • 编译gdb
      • 移植gdbserver
    • 使用GDB 进行嵌入式程序调试
      • 编写一个测试应用
      • GDB 调试程序
  • VSCode+gdbserver 图形化调试
    • VSCode 设置
    • VSCode 调试方法

开发板 FTP 服务器移植与搭建

我们可以将ALPHA 开发板作为一个小型的FTP 服务器,这样我们就可以通过FileZilla 软
件直接在开发板和windows 之间通过网络进行文件互传。这个需求也是个别客户提出来的,我
们觉得很不错,所以就专门写了这章教程。在开发板上搭建FTP 服务器很简单,就是vsftpd 的
移植,本章我们就来学习一下如何在ALPHA 开发板上移植vsftpd,搭建一个FTP 服务器。

vsftpd 源码下载

vsftpd 是一个在UNIX 类操作系统上运行的FTP 服务器名字,全称是“very secure FTP
daemon”,vsftpd 是一个完全免费、开源的FTP 服务器软件,vsftpd 在linux 发行版中非常流行。
我们在《第四章开发环境搭建》中已经给大家讲解了如何在ubuntu 下安装vsfptd,ubuntu
下安装vsfptd 很简单,直接使用apt 命令安装即可。现在我们需要在自己制作的根文件系统中
安装vsftpd,所以就需要我们自己移植vsfpd。首先需要到vsftpd 官网下载vsftpd 源码,网址为
https://security.appspot.com/vsftpd.html。注意!此网站为国外网站,因此大家可能打不开。打不
开的话也不用担心,我们已经将vsftpd 源码放到了开发板光盘中,路径为:开发板光盘A-基础
资料-》1、例程源码-》7、第三方库源码-》vsftpd-3.0.3.tar.gz。vsftpd 官网打开以后如图B1.1.1
所示:
在这里插入图片描述

图B1.1.1 vsftpd 官网
点击图B1.1.1 中的“Online source/docs”,跳转到vsftpd 源码下载页面,如图B1.1.2 所示:
在这里插入图片描述
图B1.1.2 下载vsftpd
从图B1.1.2 可以看出目前最新的版本为3.0.3 ,点击
https://security.appspot.com/downloads/vsftpd-3.0.3.tar.gz 即可下载。

vsftpd 移植

vsftpd 源码获取到以后就是移植工作了,将vsftpd-3.0.3.tar.gz 发送到ubuntu 中,然后使用
如下命令进行解压:

tar -vxzf vsftpd-3.0.3.tar.gz //解压缩

解压缩完成以后会得到一个名为“vsftpd-3.0.3”的文件夹,输入如下命令进入到此文件夹:

cd cd vsftpd-3.0.3 //进入到vsftpd 源码目录

打开Makefile,我们需要配置一下,修改Makefile 中的CC 变量为我们所使用的交叉编译
器:

CC = arm-linux-gnueabihf-gcc //CC 为交叉编译器

Makefile 修改完成以后就可以编译:

make //编译vsftpd

等待编译完成,会得到两个文件:vsftpd 和vsftpd.conf,我们需要这两个文件。将vsftpd 拷
贝到开发板根文件系统下的/usr/sbin 目录下,将vsftpd.conf 拷贝到开发板根文件系统的/etc 目录
下,命令如下:

sudo cp vsftpd /home/zuozhongkai/linux/nfs/rootfs/usr/sbin/ //拷贝vsftpd
sudo cp vsftpd.conf /home/zuozhongkai/linux/nfs/rootfs/etc/ //拷贝vsftpd.conf

拷贝完成以后给予vsftpd 可执行权限,并且修改vsfptd.conf 所属用户为root,命令如下:

chmod +x /usr/sbin/vsftpd
chown root:root /etc/vsftpd.conf

至此,vsftpd 就已经移植成功了,接下来就是测试一下。

vsftpd 服务器测试

配置vsftpd

我们要先配置一下vsftpd,打开vsftpd.conf,然后将下面两行配置前面的“#”删除掉:

local_enable=YES //取消前面的“#”
write_enable=YES //取消前面的“#”

配置完成以后如图B1.3.1.2 所示:
在这里插入图片描述

图B1.3.1.2 修改后的vsftpd.conf

添加新用户

如果第一次添加用户的话要先将ubuntu 下的/etc/passwd 和/etc/group 这两个文件复制到开
发板根文件系统的对应目录,命令如下:

sudo cp /etc/passwd /home/zuozhongkai/linux/nfs/rootfs/etc/ -f
sudo cp /etc/group /home/zuozhongkai/linux/nfs/rootfs/etc/ -f

然后修改开发板根文件系统中的/etc/passwd 和/etc/group 这两个文件,只保留“root”这一
项。passwd 文件“root”行最后改为“/bin/sh”,修改后的passwd 和group 文件内容如图B1.3.2.1
和B1.3.2.2 所示:
在这里插入图片描述

图B1.3.2.2 修改后的passwd 文件
在这里插入图片描述

图B1.3.2.3 修改后的group 文件
vsftpd 默认需要两个用户,这两个用户名分别为:“ftp”和“nobody”。在创建这两个用户
之前先检查一下下面几个文件和目录是否存在,如果不存在的话需要先创建下面这些文件和目
录:

/home //目录,不存在的话自行创建
/usr/share/empty //目录,不存在的话自行创建
/var/log //目录,不存在的话自行创建
/var/log/vsftpd.log //文件,不存在的话自行创建

创建命令如下:

mkdir /home
mkdir /usr/share/empty -p
mkdir /var/log -p
touch /var/log/vsftpd.log

准备好以后就可以使用“adduser”命令创建“ftp”和“nobody”这两个用户,命令如下:

adduser ftp //创建ftp 用户
adduser nobody //创建nobody 用户

创建过程如图B1.3.2.3 所示:
在这里插入图片描述
图B1.3.2.3 ftp 和nobody 用户创建过程
最后我们还需要创建一个登录用户,Filezilla 连接FTP 服务器的时候一般需要输入用户名
和密码,当然了,Filezilla 也支持匿名登录。如果要使用用户名加密码登录的话就要创建一个用
户,用户名自己定义,这里我创建一个名为“zuozhogkai”的用户,命令如下:

adduser zuozhongkai //创建登录要用户

最终会在/home 目录下存在三个用户目录,分别对应“ftp”、“nobody”和“zuozhongkai”,
如图B1.3.2.4 所示:
在这里插入图片描述

图B1.3.2.4 三个用户目录

Filezilla 连接测试

测试之前确保直接开发板网络连接正常,电脑可以ping 通开发板!
输入如下命令,启动vsftpd 服务器:

vsftpd & //启动vsftpd

vsftpd 启动以后就可以使用filezilla 进行连接测试了,新建站点,站点设置如图B1.3.3.1 所
示:
在这里插入图片描述
设置好以后就可以连接了,连接成功以后如图B1.3.3.2 所示:
在这里插入图片描述

图B1.3.3.2 Filezilla 连接成功
连接成功以后重新打包根文件系统,然后通过Mfgtool 将根文件系统烧写到开发板的
EMMC 或者NAND 中。根文件系统烧写完成以后重启开发板,然后启动vsftpd 服务,Filezilla
连接到开发板的FTP 服务器上。连接成功以后我们就可以通过拖拽的方式从windows 向开发板,或者从开发板向windows 下传输文件了。
注意,只能向用户目录下传输文件!比如我使用“zuozhongkai”这个用户登录的FTP 服务
器,因此只能与开发板的/home/zuozhongkai 目录进行文件互传。
我这里向开发板的/home/zuozhongkai 目录发送了一个视频文件,传输速度如图B1.3.3.3 所
示:
在这里插入图片描述

图B1.3.3.3 FTP 文件传输过程
从图B1.3.3.3 可以看出,Windows 向开发板发送文件的速度基本在11~12MB/S 之间,换算
成网速就是88~96Mbps/S,I.MX6ULL 的网口是100Mbps,可以看出FTP 传输的速度还是不错
的。当然了也与你所使用的存储设备速度有关,笔者采用EMMC 核心板进行测试,EMMC 的
读写速度要比NAND 快很多,如果使用NAND 核心板的话速度可能会下降。
我们可以设置vsftpd 开机自启动,在/etc/init.d/rcS 里面启动vsftpd 服务,在rcS 文件里面添
加如下内容即可:

vsftpd &

这样我们每次开机以后就会自动启动vsftpd 了。

开发板 OpenSSH 移植与使用

有时候我们需要远程登录到开发板上对系统进行一些操作,这个时候就要使用到SSH 服
务。SSH 是较可靠、专为远程登录会话和其他网络服务提供安全性的协议,OpenSSH 是SSH 协
议的免费开源版本,本章我们就来学习一下如何在开发板中移植OpenSSH,实现SSH 服务。

OpenSSH 简介

SSH 全称为Secure Shell(安全外壳协议,简称SSH),是一种加密的网络传输协议,用于在
不安全的网络中为网络服务提供安全的传输环境。SSH 功能很强大,但是最常用的还是用于远
程登录。OpenSSH 是SSH 协议的具体实现,OpenSSH 是一款开源、免费的SSH 软件,提供了
服务器端后台程序和客户端工具,OpenSSH 提供了很多程序,常用有以下几个:
1、ssh
ssh 软件用于替换rlogin 与Telnet。
2、scp 和sftp
将文件复制到其他主机上,用于替换rcp。
3、sshd
SSH 服务器。

OpenSSH 移植

OpenSSH 源码获取

这里我们一共需要移植三个软件包:zlib、openssl 和openssh。依次到这三个软件的官网下
载对应的源码,官网如下:
zlib 官网:http://www.zlib.net/。
openssl 官网:https://www.openssl.org/source/。
openssh 官网:http://www.openssh.com/。
这三个软件的源码我们已经放到了开发板光盘中,路径为:1、例程源码->7、第三方库源
码->zlib-1.2.11.tar.gz、openssl-1.1.1d.tar.gz 和openssh-8.2p1.tar.gz。接下来就依次编译、移植这三
个软件。

移植zlib 库

参考65.7.1 章节: Linux 音频驱动实验

移植openssl 库

参考70.3.1 章节:Linux WIFI驱动实验

移植openssh 库

1、交叉编译openssh 库
先解压openssh 源码,命令如下:

tar -vxzf openssh-8.2p1.tar.gz

解压完成以后就会生成一个名为“openssh-8.2p1”的文件夹,进入此文件夹里面,然后配置
并编译openssh,命令如下:

cd openssh-8.2p1/
./configure --host=arm-linux-gnueabihf --with-libs --with-zlib=/home/zuozhongkai/linux/IMX6ULL/tool/zlib --with-ssl-dir=/home/zuozhongkai/linux/IMX6ULL/tool/openssl --disable-etc-default-login CC=arm-linux-gnueabihf-gcc AR=arm-linux-gnueabihf-ar //配置
make //编译

在配置openssh 的过程中,“–with-zlib”参数用于指定zlib 库所在的目录,“–with-ssl-dir”
参数用于指定openssl 库所在的目录,编译openssh 的时候不用“make install”。
2、将openssh 相关文件拷贝到开发板中
openssh 交叉编译完成以后在开发板中创建如下所示目录(如果存在的话就不需要创建):

/usr/local/bin
/usr/local/sbin
/usr/local/libexec
/usr/local/etc
/var/run
/var/empty

创建命令如下:

mkdir /usr/local/bin -p
mkdir /usr/local/sbin -p
mkdir /usr/local/libexec/ -p
mkdir /usr/local/etc -p
mkdir /var/run -p
mkdir /var/empty/ -p

上述目录创建好以后将如下文件拷贝到开发板的/usr/local/bin 目录下:

scp sftp ssh ssh-add ssh-agent ssh-keygen ssh-keyscan

将如下文件拷贝到开发板的/usr/local/sbin 目录下:

sshd

将如下文件拷贝到开发板的/usr/local/etc 目录下:

moduli ssh_config sshd_config

将如下文件拷贝到开发板的/usr/local/libexec 目录下:

sftp-server ssh-keysign

创建软连接,进入开发板中的/bin 目录下,输入如下命令创建软连接:

cd /bin/
ln -s /usr/local/bin/scp
ln -s /usr/local/bin/sftp
ln -s /usr/local/bin/ssh
ln -s /usr/local/bin/ssh-add
ln -s /usr/local/bin/ssh-agent
ln -s /usr/local/bin/ssh-keygen
ln -s /usr/local/bin/ssh-keyscan

再进入开发板的/sbin 目录下,输入如下命令创建软连接:

cd /sbin/
ln -s /usr/local/sbin/sshd

软连接创建完成以后就可以直接调用上面ssh 相关命令了。
打开/usr/local/etc/sshd_config 文件,找到“#PermitRootLogin”所在行,将其改为“
PermitRootLogin yes”。

openssh 设置

1、添加sshd 用户
首先添加“sshd”用户,在使用adduser 命令添加sshd 用户的时候需要检查一些文件或目
录是否存在,具体参考B1.3.2 章节。当所需的文件都存在以后就可以使用adduser 创建名为“sshd”
的用户了,创建sshd 用户的时候需要设置密码,大家一定要记得这个密码,这里我设置简单一
点,为“123456”,创建过程如图B2.3.1 所示:
在这里插入图片描述

图B2.3.1 sshd 用户添加过程
2、在开发板上生成秘钥文件
一切准备好以后我们还需要在开发板中生成秘钥文件,使用我们上面移植openssh 所编译
出来的ssh-keygen 软件即可。进入到开发板的/usr/local/etc 目录下,输入如下所示命令生成秘钥
文件,由于6ULL 性能比较差,有些秘钥文件生成过程可以会有点耗时,打开几十秒:

ssh-keygen -t rsa -f ssh_host_rsa_key -N ""
ssh-keygen -t dsa -f ssh_host_dsa_key -N ""
ssh-keygen -t ecdsa -f ssh_host_ecdsa_key -N ""
ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N ""

完成以后就会在/usr/local/etc 目录下产生8 个以“ssh_host_”开头的秘钥文件,如图B2.3.1
所示:
在这里插入图片描述

图B2.3.1 生成的秘钥文件

openssh 使用

openssh 移植已经移植到了开发板中,我们可以通过sshd 软件在开发板上搭建openssh 服
务器,然后在其他的主机上通过ssh 来登录开发板。我们可以同样使用scp 命令来向开发板传
输文件。首先要在开发板上启动ssh 服务,sshd 软件用于启动ssh 服务,注意要输入全路径!输
入如下命令:

/sbin/sshd //启动sshd 服务

也可以在/etc/init.d/rcS 文件中加入如下命令,实现ssh 服务开机自启动:

/sbin/sshd &

ssh 登录

启动以后我们就可以使用XobaXterm、SecureCRT 等终端软件通过SSH 服务登录开发板,这里以XobaXterm 为例讲解一下。打开XobaXterm 软件,点击“Session”按钮,在弹出的
“Session settings”界面上选择“SSH”。在“Remote host”栏输入开发板IP 地址,在“Specify
username”栏输入登录用户名,比如我们上面创建的“sshd”用户,配置完成以后如图B2.4.1.1
所示:

在这里插入图片描述
图B2.4.1.1 SSH 配置
配置完成以后点击“OK”按钮,此时就会打开ssh 会话框,如图B2.4.1.2 所示:
在这里插入图片描述

图B2.4.1.2 SSH 登录
输入sshd 用户密码,可能会弹出是否保存密码对话框,选择保存即可。如果密码正确的话
就会登录到开发板上,如图B2.4.1.3 所示:
在这里插入图片描述
图B2.4.1.3 SSH 登录成功
SSH 登录成功以后我们就可以直接对开发板进行各种操作了。
同样的,我们也可以在ubuntu 下通过ssh 命令登录开发板,输入如下命令:

ssh sshd@192.168.1.251

其中“sshd”为登录账户名字,192.168.1.251 是开发板的IP 地址。用户名和开发板IP 地址
之间用“@”符号链接起来。第一次与开发板建立连接的时候会让你进行确认,输入“yes”就
行了,如图B2.4.1.4 所示:
在这里插入图片描述

图B2.4.1.4 确认建立连接
输入“yes”以后就会让你输入“sshd”用户密码,如图B2.4.1.5 所示:
在这里插入图片描述

图B2.4.1.5 输入sshd 用户密码
如果密码正确的话就会登录进开发板,可以对开发板进行各种操作,如图B2.4.1.6 所示:
在这里插入图片描述

图B2.4.1.6 通过SSH 对开发板进行操作
输入“exit”命令即可退出SSH 会话。

scp 命令拷贝文件

如果我们要向开发板发送一个文件,我们可以通过TF 卡或者U 盘来中转,或者通过我们
上一章讲的tftp 来发送。本章我们移植openssh 的时候也编译出来了一个名为“scp”的命令,
所以我们可以在开发板中使用scp 命令向其他主机发送文件,同样的其他主机也可以使用scp命令向开发板发送文件。比如我们要把ubuntu 中的一个文件发送到开发板中,输入如下命令即
可:

scp seriaApp sshd@192.168.1.251

将seriaApp 文件发送到开发板中,发送完成以后就会在开发板的根目录下看到此文件,如
图B2.4.2.1 所示:
在这里插入图片描述

图B2.4.2.1 scp 命令拷贝结果
关于openssh 就讲解到这里,通过ssh 大家就可以远程登录开发板了。

嵌入式GDB 调试搭建与使用

在学习单片机的时候我们可以通过集成式IDE 来进行调试,比如MDK、IAR 等。在嵌入
式linux 领域是否也可以进行调试呢?答案肯定是可以的,在嵌入式linux 领域我们最常用的就
是GDB 调试工具,通过GDB 来调试嵌入式C 程序。本章我们首先学习如何搭建嵌入式Linux
的GDB 调试环境,然后讲解如何使用GDB 工具调试C 程序。

GDB 简介

gdb 工具是GNU 项目调试器,基于命令行。和其他的调试器一样,我们可以使用gdb 来一
行行的运行程序、单步执行、跳入/跳出函数、设置断点、查看变量等等,它是UNIX/LINUX 操
作系统下强大的程序调试工具。gdb 支持多种语言,包括Ada、汇编、C/C++、D、Fortran、GO、
Objective-C、OpenCL、Modula-2、Pascal 和Rust。关于gdb 更多详细的信息请到gdb 官网查阅,
gdb 官网地址为:www.gnu.org。
一般的桌面Linux 系统,比如ubuntu、centos 等,我们可以直接运行gdb 来调试程序。但
是嵌入式中芯片性能一般比较弱,所以直接在嵌入式系统中运行gdb 不太现实(性能强大的嵌入
式芯片可以这么做)。嵌入式系统中一般在PC 端运行gdb 工具,源码也是在PC 端,源码对应
的可执行文件放到开发板中运行。为此我们需要在开发板中运行gdbserver,通过网络与PC 端
的gdb 进行通信。因此要想在PC 上通过gdb 调试嵌入式程序,那么需要两个东西:gdb 和
gdbserver,其中gdb 是运行在PC 上的,gdbserver 需要我们移植到开发板上。

GDB 移植

一般交叉编译已经自带了gdb 和gdbserver,因此可以不用移植,直接使用交叉编译器自带
的即可。比如本教程所使用的arm-linux-gnueabihf-gcc 就自带了主机使用的arm-linux-gnueabihf-gdb 和开发板所使用的gdbserver。进入ubuntu 中交叉编译器安装目录中的bin 文件夹下,比如
笔者的就是/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin,此目录中就包
含了arm-linux-gnueabihf-gdb 和gdbserver,如图B3.2.1 所示:
在这里插入图片描述

图B3.2.1 交叉编译自带的gdb 和gdbserver
如果交叉编译器自带了gdb 和gdbserver 的话只需要将gdbserver 拷贝到开发板根文件系统
的/bin 目录下,然后直接看B3.3 章节。
如果交叉编译器没有自带gdb 和gdbserver 那就需要自己手动编译了,继续看本节即可。

获取gdb 和gdbserver 源码

首先到gdb 官网上获取源码,地址为http://www.gnu.org/software/gdb/download/,在笔者写
本教程的时候,最新的gdb 源码版本为9.1。已经放到了开发板光盘中,路径为:1、例程源码
->7、第三方库源码-> gdb-9.1.tar.gz。将gdb 源码发送到ubuntu 中中并解压,命令如下:

tar -vxzf gdb-9.1.tar.gz //加压gdb 源码

解压完成以后就会得到一个名为gdb-9.1 的文件夹,此文件夹就是gdb 和gdbserver 源码,
其中gdb-9.1/gdb/gdbserver 目录就是gdbserver 源码。

编译gdb

1、编译gdb
首先编译gdb,gdb 是运行在PC 端的程序,gdb 编译的时候需要进行配置,配置项如下:
–target:目标机交叉编译器前缀,也就是你所使用的交叉编译器前缀,比如在本教程中就
设置为arm-linux-gnueabihf。
–host:指定编译后的程序在哪里运行,编译gdb 的时候就需用设置,因为我们是需要在PC
上运行的,编译gdbserver 的时候就要设置为arm-linux。
–prefix:指定安装目录。
创建一个名为“gdb”的文件夹,用来保存编译后的gdb 和gdbserver,路径自行选择。gdb
编译比较奇葩!使用如下命令配置并编译gdb:

cd gdb-9.1/ //进入gdb 源码目录
mkdir build //在gdb 源码下新建build 目录,gdb 编译比较奇葩!不能直接在gdb 源
//码目录下进行配置和编译,必须新建一个文件夹,然后在此文件夹下配
//置和编译,切记!
cd build //进入到刚刚创建的build 目录下
../configure --target=arm-linux-gnueabihf --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/gdb
//配置gdb。配置完成以后会在build 目录下生成Makefile 文件。
make //编译
make install //安装

编译完成以后PC 端运行的gdb 工具就会安装到gdb/bin 目录下,名字为arm-linux-gnueabihf-
gdb,如图B3.2.2.1 所示:
在这里插入图片描述

图B3.2.2.1 编译后的gdb 工具
图B3.2.2.1 中的arm-linux-gnueabihf-gdb 就会我们编译得到的gdb 工具,输入如下命令运
行此gdb:

cd gdb/bin //进入到bin 目录下
./arm-linux-gnueabihf-gdb //运行此gdb

结果如图B2.2.2.2 所示:
在这里插入图片描述

图B3.2.2.2 gdb 运行结果
从图B3.2.2.2 可以看出,arm-linux-gnueabihf-gdb 版本号为9.1,说明编译安装成功,输入
“q”可以退出gdb 工具。
2、关闭交叉编译器自带的gdb
我们安装的arm-linux-gnueabihf 交叉编译器已经默认自带了一个名为“arm-linux-gnueabihf-gdb”的gdb 工具!大家可以到自己的交叉编译器安装目录看一下,相对路径为:gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin,如图B3.2.2.3 所示:
在这里插入图片描述

图B3.2.2.3 交叉编译器自带的gdb 工具
从图B3.2.2.3 可以看出,编译器自带的gdb 工具和我们编译出来的gdb 名字一样,这两个
都可以使用,也就是说我们可以不用自行编译gdb,直接使用交叉编译器里面的也是可以的!
只是这两个gdb 的版本号可能不一样,可以查看一下交叉编译器自带的gdb 工具版本号,我这
里如图B3.2.2.4 所示:
在这里插入图片描述

图B3.2.2.4 交叉编译器自带gdb 工具版本号
从图B3.2.2.4 可以看出,交叉编译器自带的gdb 工具版本号为7.10。现在有个问题,一山
不能容二虎,9.1 版本和7.10 版本只能留一个,我测试过,这两个任意哪一个都可以。这里我
们使用自己编译的9.1 版本的gdb 工具,因此需要对交叉编译器自带的7.10 版本的gdb 工具重
命名,这里笔者将其重命名为“arm-linux-gdb”。
最后打开ubuntu 的/etc/profile 文件,修改PATH 环境变量值,将我们编译出来的9.1 版本
的“arm-linux-gnueabihf-gdb”所在的路径添加进去,这样我们就可以直接使用此gdb 了,根据
自己的实际情况修改PATH 值,比如我的PATH 内容如下:

export PATH=/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin:/home/
zuozhongkai/linux/IMX6ULL/tool/gdb/bin:$PATH

其中红色加粗部分就是我所编译出来的9.1 版本gdb 工具所存放的路径,修改完以后重启
ubuntu,这个时候我们就可以使用命令“arm-linux-gnueabihf-gdb”来打开gdb 调试器了。

移植gdbserver

接下来移植gdbserver,gdbserver 是在开发板上运行的,因此要交叉编译。gdbserver 源码保
存在gdb-9.1/gdb/gdbserver 目录下,进入此目录,然后输入如下命令配置并编译:

cd gdb-9.1/gdb/gdbserver //进入到gdbserver 目录
./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf //配置
make CC=arm-linux-gnueabihf-gcc //交叉编译gdbserver

编译完成以后就会在目录下生成一个名为“gdbserver”的文件,这个就是我们需要放到开
发板上去的gdbserver,如图B3.2.3.1 所示:
在这里插入图片描述

图B3.2.3.1 gdbserver 软件
将图B3.2.3.1 中交叉编译出来的gdbserver 软件发送到开发板中的/usr/bin 目录下,完成以
后在开发板中输入如下命令查看gdbserver 版本号:

gdbserver –version //查看版本号

如果gdbserver 移植成功的话就会打印出其版本号,如图B3.2.3.2 所示:
在这里插入图片描述

图B3.2.3.2 gdbserver 版本号
从图B3.2.3.2 可以看出,当前gdbserver 版本号为9.1,说明我们的移植是成功的。PC 上的
gdb 和开发板上的gdbserver 都已经准备好了,接下来就是使用这两个工具来完成调试。

使用GDB 进行嵌入式程序调试

编写一个测试应用

首先编写一个简单的测试软件,我们一会就用gdb 来调试这个软件,新建名为gdbtest.c 的
文件,在里面输入如下所示内容:

示例代码B3.3.1.1 gdbtest.c 测试代码
1 #include <stdio.h>
2 #include <unistd.h>
3
4 int main(int argc, char *argv[])
5 {
6 unsigned int times = 0;
7
8 while(1) {
9 printf("runing times:%d\r\n", times);
10 times++;
11 sleep(1);
12 }
13 }

使用arm-linux-gnueabihf-gcc 交叉编译gdbtest.c 文件,要想调试程序,那么编译的时候必
须加上“-g”选项,这样编译出来的可执行文件才带有调试信息,这一点一定要切记!编译命
令如下所示:

arm-linux-gnueabihf-gcc gdbtest.c -o gdbtest -g //编译测试程序,注意-g 选项

编译完成以后将得到的gdbtest 可执行文件发送到开发板中。

GDB 调试程序

一切准备就绪以后就可以使用GDB 进行调试了,确保ubuntu 和开发板可以进行网络通信。
在开发板中输入如下命令:

gdbserver 192.168.1.253:2001 gdbtest //启动开发板上的gdbserver

上述命令中192.168.1.253 为调试机的IP 地址,也就是ubuntu 的IP 地址,2001 是端口号,
可以任意给一个端口号,gdbtest 是要调试的可执行文件。输入以后开发板输出信息如图B3.3.2.1
所示:
在这里插入图片描述

图B3.3.2.1 开发板上gdbserver 运行
接着在ubuntu 中输入如下命令启动gdb 调试工具:

arm-linux-gdb gdbtest

结果如图B3.3.2.2 所示:
在这里插入图片描述

图B3.3.2.2 ubuntu 执行gdb 命令
图B3.3.2.2 中最下面的(gdb)行用于输入命令,输入如下命令连接到开发板上:

target remote 192.168.1.251:2001 //连接到开发板上

上述命令表示连接到开发板上,其中192.168.1.251 就是开发板IP 地址,2001 就是开发板
gdbserver 设置的端口号。连接成功以后开发板中的gdbserver 就会提示连接信息,如图B2.3.2.3
所示:
在这里插入图片描述

图B3.3.2.3 调试机与开发板连接成功
从图B3.3.2.3 可以看出,远端调试机的IP 地址为192.168.1.253,也就是我们的ubuntu 址,连接成功以后就可以在ubuntu 上进行代码调试了。gdb 工具是一个基于命令行的调试工具,我
们就来学习一下常用的几个命令。
1、l 命令
l 命令(list)用于列出所有程序源码,输入“l”,结果如图B3.3.2.4 所示:
在这里插入图片描述

图B3.3.2.4 l 命令运行结果
从图B3.3.2.4 可以看出,输入“l”命令以后就打印出了调试程序的所有源码,如果源码没
有打印完的话就重复按下“l”命令,或者按下回车键,gdb 调试工具中回车键表示重复上一个
命令!
2、b 命令
b 命令(break)用于设置断点,也可以用缩写“b”,后面可以跟具体的函数或者行号,比如
“break main”表示在main 函数处设置断点,“break 11”在第11 行设置断点。输入如下命令,
在main 函数处设置断点:

b main 或break main

设置以后提示如图B3.3.2.5 所示:
在这里插入图片描述

图B3.3.2.5 在main 函数处设置断点
从图B3.3.2.5 可以看出,断点1 设置到了gdbtest.c 的第6 行,大家可以看一下图B3.3.2.4,
第6 行正好是main 函数的起始处。
3、c 命令
c 命令用于运行到断点处,输入c 命令程序就会运行,直到下一个断点处,如图B3.3.2.6 所
示:

在这里插入图片描述
图B3.3.2.6 c 命令运行结果
从图B3.3.2.6 可以看出,当前程序运行到第6 行停止,因为我们前面在第6 行放置了一个
断点,因此程序运行停止。继续输入“c”命令,程序就会持续不断的运行,开发板中就会不断
的打印出信息,如图B3.3.2.7 所示:
在这里插入图片描述

图B3.3.2.7 程序继续运行
4、s 命令
s 命令(step)是单步运行执行,此函数会进入到函数里面。
5、n 命令
n 命令(next)也是单步运行,但是n 命令不会进入到函数里面。
6、p 命令
p 命令(print)用于打印某个变量值。
7、q 命令
q 命令(quit)用于退出调试,开发板上的gdbserver 也会停止。
关于gdb 调试更多详细的使用方法和命令大家自行上网查阅,这里就不一一介绍了。

VSCode+gdbserver 图形化调试

上一章我们讲了如何使用gdb+gdbserver 实现对嵌入式linux 程序的调试,由于主机上的
gdb 工具是基于命令行的,因此调试起来不方便,虽然可以加一些插件,但是依旧和IDE 的调
试体验差很多。本章我们就来学习一下,如何使用VSCode+gdbserver 来实现图形化界面的嵌入
式linux 程序调试。

VSCode 设置

给VScode 安装远程调试插件“Remote Development”,点击“调试”->“添加配置”,然后
选择“C++(GDB/LLDB)”选项,如图B4.1.1 所示:
在这里插入图片描述

图B4.1.1 选择调试配置文件
选择图B4.1.1 中的“C++(GDB/LLDB)”,会在当前文件夹新建一个名为“launch.json”的文
件,此文件会存放在.vscode 目录下,如图B4.1.2 所示:
在这里插入图片描述

图B4.1.2 launch.json 文件
launch.json 文件默认的内容如下所示:

示例代码B4.1.2 launch.json 文件默认内容
1 {
2 // 使用IntelliSense 了解相关属性。
3 // 悬停以查看现有属性的描述。
4 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5 "version": "0.2.0",
6 "configurations": [
7 {
8 "name": "(gdb) 启动",
9 "type": "cppdbg",
10 "request": "launch",
11 "program": "输入程序名称,例如${workspaceFolder}/a.out",
12 "args": [],
13 "stopAtEntry": false,
14 "cwd": "${workspaceFolder}",
15 "environment": [],
16 "externalConsole": false,
17 "MIMode": "gdb",
18 "setupCommands": [
19 {
20 "description": "为gdb 启用整齐打印",
21 "text": "-enable-pretty-printing",
22 "ignoreFailures": true
23 }
24 ]
25 }
26 ]
27 }

launch.json 文件中有几个项目是需要我们根据实际情况配置的:
①、name:调试的项目名
②、program:需要调试的应用程序可执行文件路径。
③、cwd:需要调试的应用程序源码路径。
④、miDebuggerPath:此项需要手动添加,用于指定所使用的交叉编译器gdb 路径。
⑤、miDebuggerServerAddress:此项需要手动添加,远程gdbserver 服务器地址。
修改完成以后的launch.json 文件内容如下所示:

示例代码B4.1.3 launch.json 配置好的内容
1 {
......
5 "version": "0.2.0",
6 "configurations": [
7 {
8 "name": "gdbtest",
9 "type": "cppdbg",
10 "request": "launch",
11 "program": "${workspaceFolder}/gdbtest",
12 "args": [],
13 "stopAtEntry": false,
14 "cwd": "${workspaceFolder}",
......
25 "miDebuggerPath": "/home/zuozhongkai/linux/IMX6ULL/tool/gdb/bin/arm-linux-gnueabihf-gdb",
26 "miDebuggerServerAddress": "192.168.1.251:2001"
27
28 }
29 ]
30 }

注意示例代码B4.1.3 中加粗的部分就是我根据自己的实际情况所填写的内容。

VSCode 调试方法

VSCode 设置好以后就可以进行调试了,首先要启动开发板上的gdbserver,输入如下命令:

gdbserver 192.168.1.253:2001 gdbtest

接下来在点击VSCode 上的“调试”->“启动调试”按钮,如图B4.2.1 所示:
在这里插入图片描述
图B4.2.1 启动调试
由于是通过网络进行调试的,因此启动调试以后会有一个建立连接的过程,可能需要几秒
钟,建立成功以后如图B4.2.2 所示:
在这里插入图片描述

图B4.2.2 调试界面
图B4.2.2 就是调试界面,调试功能非常强大,简单介绍一下调试方法。
1、控制程序运行
首先肯定是如何控制程序运行,在VSCode 上方居中的位置有如图B4.2.3 所示控制面板:
在这里插入图片描述

图B4.2.3 程序运行控制面板
可以看出,一共有6 个控制按钮,这6 个按钮从左往右功能及快捷键依次如下:
①、继续按钮,快捷键为F5,用于控制程序的运行和暂停,程序运行到断点暂停以后可以
按下此按钮继续运行。
②、单步跳过按钮,快捷键为F10。
③、单步调试按钮,快捷键为F11。
④、单步跳出按钮,快捷键为Shift+F11。
⑤、重启按钮,快捷键为Ctrl+Shift+F5。
⑥、停止按钮,快捷键为Shift+F5。
2、断点添加
添加断点的方式也很简单,在需要添加断点的行前面,直接点击即可添加或取消断点,断点添加成功以后会在所在行前面显示一个小红点,如图B4.2.4 所示:
在这里插入图片描述

图B4.2.4 添加断点
3、监视变量
有时候我们需要监视一个变量的变化,这个也很简单,鼠标双击选中需要监视的变量名
上,然后点击鼠标右键,选择“调试:添加到监视器”,如图B4.2.5 所示:
在这里插入图片描述

图B4.2.5 添加变量到调试器
添加成功以后我们就可以在左侧的“监视”窗口看到刚刚添加的变量,如图B4.2.6 所示:
在这里插入图片描述

图B4.2.6 监视的变量
关于VSCode 调试嵌入式linux 程序的方法就介绍到这里,大家可以多练习几次,以后编写
linux 应用的时候就可以通过VSCode 来进行图形化调试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/123019.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java SE 学习笔记(十七)—— 单元测试、反射

目录 1 单元测试1.1 单元测试概述1.2 单元测试快速入门1.3 JUnit 常用注解 2 反射2.1 反射概述2.2 获取类对象2.3 获取构造器对象2.4 获取成员变量对象2.5 获取常用方法对象2.6 反射的作用2.6.1 绕过编译阶段为集合添加数据2.6.2 通用框架的底层原理 1 单元测试 1.1 单元测试概…

简单而高效:使用PHP爬虫从网易音乐获取音频的方法

概述 网易音乐是一个流行的在线音乐平台&#xff0c;提供了海量的音乐资源和服务。如果你想从网易音乐下载音频文件&#xff0c;你可能会遇到一些困难&#xff0c;因为网易音乐对其音频资源进行了加密和防盗链的处理。本文将介绍一种使用PHP爬虫从网易音乐获取音频的方法&…

【python笔记】小甲鱼

P3 查看内置函数 dir(__builtins__) P4 变量名命名规则&#xff1a; 1、变量名不能以数字打头&#xff1b; 2、变量名可以是中文 字符串可以是&#xff1a; 1、单引号&#xff1a;文本中存在双引号时使用单引号 2、双引号&#xff1a;文本中存在单引号时使用双引号 当…

Linux创建逻辑卷并扩容(超详细)

目录 ​编辑 一、概念解析 1、LV逻辑卷 2、PV物理卷 3、VG卷组 二、扩容前准备 三、创建逻辑卷并扩容 1、打开虚拟机 2、进入root用户 3、查看新加入的硬盘 4、创建主分区 5、创建物理卷 6、打包为一个卷组 7、创建逻辑卷 8、格式化逻辑卷 9、挂载逻辑卷--开机自…

Go学习第十四章——Gin请求与响应

Go web框架——Gin请求与响应 1 响应1.1 String1.2 JSON&#xff08;*&#xff09;1.3 HTML&#xff08;*&#xff09;1.4 XML1.5 文件&#xff08;*&#xff09; 2 请求2.1 请求参数查询参数 (Query)动态参数 (Param)表单参数 (PostForm)原始参数 (GetRawData) 2.2 请求头2.3 …

【送书福利-第二十一期】《ChatGPT进阶:提示工程入门》

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号&#xff1a;程序员洲洲。 &#x1f388; 本文专栏&#xff1a;本文…

elementUI 特定分辨率(如1920*1080)下el-row未超出一行却换行

在1920*1080分辨率下&#xff0c; el-col 内容未超出 el-col 宽度&#xff0c;el-col 不足以占据一行&#xff0c;el-row 却自动换行了&#xff08;其他分辨率没有这个问题&#xff09;。 截图&#xff1a; 排查&#xff1a; el-col 内容没有溢出&#xff1b;没有多余的 pad…

TELUS Ventures(泰勒斯)

TELUS Ventures&#xff08;泰勒斯&#xff09;高峰论坛于2023年10月28日在南京第5站正式开幕。该论坛是由泰勒斯风险投资公司主办的一项重要活动&#xff0c;旨在促进创新和创业精神的发展 。 这次高峰论坛将汇集来自全球各地的创业者、投资者和行业专家&#xff0c;共同探讨…

Mac 版 WPS 接入 WPS AI,支持内容创作、修改文章、提炼重点等功能

导读近日消息&#xff0c;“WPS 办公助手”公众号发文宣布&#xff0c;Mac 版 WPS 现已接入 WPS AI&#xff0c;将带来内容生成、内容修改、辅助阅读等功能。 汇总 Mac 版 WPS 接入 WPS AI 之后&#xff0c;在文字、PDF 方面的功能如下&#xff1a; 一键生成文章大纲、讲话稿、…

TS中类型别名和接口区别

在很多场景下&#xff0c;interface 和 type都能使用&#xff0c;因此两者在很多时候会被混淆&#xff1a; 接口可以通过之间的继承&#xff0c;实现多种接口的组合 使用类型别名也可以实现多种的&#xff0c;通过&连接,有差异&#xff1a; 子接口中不能重新覆盖父接口中…

UWB室内定位技术

室内定位系统方案中&#xff0c;UWB室内定位技术目前应用较多&#xff0c;得益于UWB室内定位10-30厘米的超高定位精度。 UWB全称是超宽带技术&#xff0c;它是一种无线载波通信技术。 UWB不采用载波&#xff0c;而是利用纳秒至微微秒级的非正弦波窄脉冲传输数据。 目前根据使用…

公众号留言功能有必要开吗?如何开通留言?

为什么公众号没有留言功能&#xff1f;2018年2月12日&#xff0c;TX新规出台&#xff1a;根据相关规定和平台规则要求&#xff0c;我们暂时调整留言功能开放规则&#xff0c;后续新注册帐号无留言功能。这就意味着2018年2月12日号之后注册的公众号不论个人主体还是组织主体&…

队列(8.6)

目录 2.队列 2.1队列的概念及结构 2.2队列的实现 2.2.1初始化队列 2.2.2队尾入队列 2.2.3队头出队列 2.2.4获取队列头部元素 2.2.5 销毁队列 3.栈和队列面试题 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 232. 用栈实现队列 - 力扣&#xff08;LeetC…

力扣每日一题73:矩阵置零

题目描述&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2…

java集成海康预览抓图出现内存一直上涨问题

求助&#xff1a;在java 中集成海康sdk后批量抓图出现内存上涨问题&#xff0c;不论是预览后不关闭继续预览&#xff0c;还是预览后关闭预览&#xff0c;然后重新预览都没有解决这个问题&#xff08;抓图正常&#xff09;&#xff0c;尝试使用第三方解码器ffmpeg来进行解码&…

刀具磨损状态识别(Python代码,MSCNN_LSTM_Attention模型,初期磨损、正常磨损和急剧磨损分类,解压缩直接运行)

1.运行效果&#xff1a;刀具磨损状态识别&#xff08;Python代码&#xff0c;MSCNN_LSTM_Attention模型&#xff0c;初期磨损、正常磨损和急剧磨损&#xff09;_哔哩哔哩_bilibili 环境库&#xff1a; NumPy 版本: 1.19.4 Pandas 版本: 0.23.4 Matplotlib 版本: 2.2.3 Keras …

Android JNI/NDK 入门从一到二

1. 前言 最基础的创建JNI接口的操作&#xff0c;可以直接看这篇文章 : 第一个Android JNI工程&#xff0c; 本文会基于掌握创建JNI接口的操作的基础之上&#xff0c;来入门JNI/NDK。 2. 在JNI中打印日志 2.1 添加log模块 记得CMake中有log模块&#xff0c;不然编译不过 ta…

正点原子嵌入式linux驱动开发——Linux 多点电容触摸屏

随着智能手机的发展&#xff0c;电容触摸屏也得到了飞速的发展。相比电阻触摸屏&#xff0c;电容触摸屏有很多的优势&#xff0c;比如支持多点触控、不需要按压&#xff0c;只需要轻轻触摸就有反应。ALIENTEK的三款RGB LCD屏幕都支持多点电容触摸&#xff0c;本章就以ATK7016这…

制作电子版宣传画册,抢占线上消费市场

随着互联网和移动设备的普及&#xff0c;企业在如今如此激烈的市场竞争中&#xff0c;怎样才能提高自身的宣传力度&#xff0c;进而让企业在市场中占一席之地呢&#xff1f;现在大多数企业都青睐于借助电子画册的形式来实现。 如何制作电子版宣传画册&#xff0c;抢占市场消费资…

基于混合蛙跳算法的无人机航迹规划-附代码

基于混合蛙跳算法的无人机航迹规划 文章目录 基于混合蛙跳算法的无人机航迹规划1.混合蛙跳搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用混合蛙跳算法来优化无人机航迹规划。 …