赞
踩
本章主要从Linux的应用场景,程序员的技能学习,职业方向来 讨论为什么需要学习Linux开发并对如何学好Linux开发提出了一些建议。
对于一般用户来说,因为经常接触PC、手机,可能会知道Windows、iOS、Andorid系统,但对Linux系统却知之甚少,这是因为 Linux的应用场景主要是服务器和嵌入式设备,在直面消费者的桌面系统领域并不占据优势。不过,从某种程度来说,Android系统也属于Linux的一种,毕竟它是基于Linux内核进行开发的,只是由于它规避了Linux的开源协议,不被Linux社区接纳。
Linux的应用场景主要是由其特点决定的,其特点主要有:开源、安全、稳定、网络功能强大、支持多种不同平台的处理器。
服务器是指提供计算服务的设备,如网页服务器、文件 服务器、数据库服务器、邮件服务器、域名服务器和代理服务 器等。可以说我们在互联网上的所有操作,背后都是在跟服务 器打交道。例如我们访问网页、网上购物、微信聊天、运行网络 游戏、观看在线视频等一切需要联网才能正常进行的应用,其背 后都由服务器作为支撑。
服务器的实体各种各样,小到单板电脑,大至计算机集群,实际上你 正在使用的个人电脑,安装上对应的服务软件,通过网络给其它计算机提 供资源,它也就变身成了一个服务器。服务器的本质也是计算机,只是通 常来说它们没有显示器,不需要鼠标键盘。
在商业应用中,在服务器运行的操作系统主要有Linux、Windows和UNIX,其中 由于Linux系统开源、使用成本低而且安全稳定,所以Linux在服务器使用的系统中占据了绝大多数。
感兴趣的读者可以访问Netcraft 网站 http://www.netcraft.com,可以查询 到其它网站是运行在什么操作系统上的,具体见下图。
特别地,超级计算机也是特殊的服务器,目前全球TOP500的计算机运行的操作系统都是Linux。
嵌入式设备是Linux系统的另一个主战场,这也是本书主 要讲解的Linux应用方向。嵌入式设备的定义比较模糊,不过基本上把PC、集群 服务器、超级计算机排除后,具有处理器(包括微控制器等)的,按设定程序运行 的电子设备大都可以归类为嵌入式设备。
嵌入式设备种类非常丰富,包括日常生活中的手机、智能手表、各 种家电、玩具、路由器、车载电子系统,工业应用中包括电力系统监控、环境 监测、工业机器人、智能快递柜、手持POS机、地铁闸机系统、停车场管理、卫星、月球车等。
从嵌入式设备的种类就可以知道它们的应用场景是碎片化的,它们内 部的电子系统一般会针对设备的功能做专用的控制。部分嵌入式设备不使用 操作系统;部分使用freeRTOS等实时操作系统;而另一些高性能的嵌入式设备 使用Linux系统。使用Linux系统的的嵌入式设备,往往是看中Linux系统的如下特性:
根据Linux的应用场景,社会对Linux技术人员主要分为服务器运维、应用软件开发及设备驱动开发方向。
服务器运维工程师主要是负责搭建起运行环境,让服务器应用程序更高效、稳定、安全地运行在服务器上。如安装操作系统、部署代码运行环境、修复漏洞、监控服务器压力、分析日志等。
Linux应用软件开发就是开发基于Linux系统的应用程序。具体而言,应用程序也分服务器、桌面和嵌入式方向,服务器方向如网站后台、数据库系统等。服务器方向的应用程序开发通常跟操作系统的关系并不是很大;桌面开发就如同开发Windows系统下的QQ、WPS、串口调试助手等应用程序;嵌入式方向的软件方向主 要是针对设备应用场景做针对性的开发,如扫地机器人、路由器的控制程序等。
设备驱动,它的本质也是软件程序,不过它介于硬件与操作系统之间的层级,是硬件和操作系统之间的桥梁,具体见下图。
对于不使用操作系统或使用小型实时操作系统(如freeRTOS)的设备来说,与硬件相关的驱动 程序与应用程序往往混合在一起,因此常常不会对驱动与应用进行严格的区分,这也导 致更换硬件平台时,应用程序移植困难。
使用了Linux系统的设备,硬件会由操作系统接管。Linux系统的一个重要设计哲 学是一切皆文件。包括硬件设备,对于系统来说也是一个文件,所以系统向上层应用程 序提供open、write、read、close等统一的文件操作接口,应用程序可以利用这些接口对 设备文件进行访问,从而实现对硬件设备的初始化、写 入、读取以及关闭等操作。
当系统接收到应用程序的这些访问请求时,它会向下查询对应设备具体的操作函数,然后调 用相应的函数处理请求,而这些针对不同设备具体的操作函数就是设备驱动程序。因此,设备驱 动就是这样一种把硬件与操作系统连接在一起的程序,Linux系统会提供统一的格式,设备驱动开 发工程师根据具体的设备按照系统格式要求实现相应 的设备操作函数。
本书主要针对嵌入式设备驱动开发的讲解,对于志在应用软件开发的工程师,也可通过本书的 内容掌握Linux底层的相关知识,这对应用开发也是大有裨益。
Linux可谓是公开的宝库,它是开源世界的代表作,它的内核源代码是完全公开的,只要你 愿意沉浸其中,必定收获丰富。通过学习Linux开发,会熟悉命令行的使用;可以了解到操作 系统原理;学习常用数据结构,如链表、红黑树、哈希表等;了解开源社区的文化,学习各自优 秀的代码实现,如常用的C语言库libc等;熟悉 各种常用开发工具,如Git版本管理系统、GCC编译器。
并不是说从事传统MCU开发或Windows开发时不能学习到这些,只是这些内容往往被包装起 来,要么直接无法追根溯源,要么隐藏起来了。但在进行Linux开发时,相关的内容是直 接暴露给用户的,只要钻得够深,永远有惊喜等待着我们。例如,使用Keil或IAR开发时, 我们不知道调用C语言库的printf函数后, 具体究竟执行了什么;点击编译按钮时,集成的工具又为我们处理了一些什么内容,这些我们都很难了解到。
对于长期从事MCU开发的程序员来说,学习Linux开发会让人感叹,原来代码的世界一直在这里等着我!
我们立足于树莓派的开发方式,借鉴其一系列先进的设计理念和软件架构,力求为电子爱好者提供强大、好用的DIY平台, 方便实现各种天马行空的想法。与此同时,所有的软件和芯片手册将全部开源,为有志于从事嵌入式linux行业者后续深入学习各种软件架构和驱动程序扫清障碍。
嵌入式linux学习者大体可以分为两类,一类是进阶用户,主要指已经有大量mcu工作经验的开发者, 他们希望进阶到更有难度,薪资更高的mpu开发中去。另一类则是学生用户,主要是刚开始接触嵌入式开发的大学生群体。
对于前者而言,出于工作的压力和升职加薪的需求,通常会比较关注课程学习的深度,关注学习完成后,能不能顺利地利用学习的知识来跳槽升职加薪。 但是对于后者,他们没有行业经验,没有工作压力,更加注重的是课程的有趣性,功能性,想知道通过这个课程我有能力做出什么东西来。
本教程兼顾两种用户的需求,首先,最大程度上降低入门门槛,这主要指两个方面,一方面简化开发环境的搭建,尽可能避免各种各样的软件版本问题, 以及各种电脑系统的兼容性问题。另一方面是先学习嵌入式linux的高频技能,所谓高频技能,就是指在大部分实际开发工作中都较为频繁地使用的技能。 其次,是尝试使用这些高频技能去开发一些炫酷、自己感兴趣的产品,进一步去了解嵌入式linux各式各样的产业,体验嵌入式linux在人类实际生活中的影响。 最后,在对嵌入式linux有整体了解后,根据自己的个人兴趣和实际工作需求,选择嵌入式linux的某一个方面深入研究。
通常,国内传统的嵌入式linux学习路线大体为:
按照上面的学习路线走下来,一方面,需要耗费巨大的学习精力,哪怕全天学习,一般也要4个月以上的时间。这对于还没有确定职业方向的学生用户, 想玩嵌入式linux的门槛太高。
另一方面,不贴合进阶用户实际工作需求,因为大部分课程在设计的时候充斥了许多低频技能,这些技能在大部分嵌入式linux工作中很少用上(比如ARM裸机开发)。 而当工作中真正遇到系统性能问题的时候,往往又没有能力去实际解决问题,因为你所学习的linux系统移植,不过是用芯片公司团队做好的系统镜像, 自己复制粘贴一些文件,修改一些配置,然后重新编译安装到系统里面去,真正高阶的技能其实没学到多少。
树莓派(Raspberry Pi)是尺寸仅有信用卡大小的一个小型电脑,您可以将树莓派连接电视、显示器、键盘鼠标等设备使用, 它的设计目标是用较为低廉的价格和大量开源软件,为青少年提供一个计算机教育平台,用于培养计算机程序设计的兴趣和能力。
现在树莓派已经拥有全球100万用户的作品展示社区,这意味着树莓派有海量的应用可以参考和模仿。 下面是它们的一些DIY案例:
考虑到开发者技术水平参差不齐,树莓派做了很多软件架构上的优化和开发了很多方便好用工具。 这是树莓派广受好评和便于在社区推广的一大原因,非常值得我们去借鉴学习。
但是树莓派也有它的不足之处,那就是它的底层的bootloader和核心数据手册是闭源的,普通用户无法获取。 所以树莓派往往更被学生群体或者其他一些创客群体所青睐,而不太适合嵌入式linux从业者的进阶学习,闭源的部分导致它在工程项目中使用也带来诸多不便。
本章简要介绍一下为什么我们采用i.MX系列应用处理器进行讲解,使用该系列芯片学习Linux开发有什么优势。
i.MX 应用处理器包括i.MX8、i.MX7、i.MX6及i.MX28系列,被广泛应用于工业控制、汽车电子领域,久经市场考验。而且它的产品线非常丰富,用户熟悉其中一款产品后就能非常方便地迁移至不同的平台。它们的前身是Freescale旗下的产品,目前属于NXP公司,所以在查阅资料和代码时, 在看到Freescale的一些标签时不要奇怪。NXP承诺对这些产品供货周期持续10年以上。学习应用处理器的驱动程序开发时,芯片原厂的技术支持是非常重要的,NXP官方提供的资料包含uboot、Linux内核的Yocto定制示例工程,完善的裸机SDK软件库等,相比之下部分芯片厂商甚至连寄存器手册都遮遮掩掩,个人 难以获取,这无疑提高了学习的门槛。
所以应用领域广泛、产品供货稳定、官方支持的资料丰富,这是我们选择它们作为学习平台的原因。
其中i.MX6系列应用处理器包含基于Cortex的单核、双核和四核系列的的产品,其架构有,主要采用Cortex-A7,Cortex-A9作为内核,部分型号采用Cortex-A9+Cortex-M4的双核心方案。主频从528MHz~1.2GHz不等。该系列芯片主要应用在车载多媒体系统、数字标牌电子阅读 器、人机界面、物联网网关、智能工业控制系统等轻量、低功耗的领域,在物联网推进的大潮下,该芯片定有一番作为。
本书讲解主要采用的是i.MX6ULL系列处理器,它包含一个Cortex-A7内核,主频有528MHz、792MHz和900Mhz,具体芯片的特性可参考图 i.MX6的命名规则图说明进行区分。如型号为MCIMX6Y2CVM08AB的芯片,它属于i.MX6ULL系列,是主频为792MHz、芯片封装为BGA,尺寸为14x14mm,焊盘间距为0.8pitch的工业级芯片。
i.MX6的命名规则图
Cortex-A7处理器是ARM开发的一种高能效处理器架构,它的架构和功能集与Cortex-A15 处理器大部分相同,不过Cortex-A7 处理器的结构侧重于功耗与性能的平衡,因此这两种处理器可在big.LITTLE(大小核伴侣架构)配置中协同工作,从而提供高性能与超低功耗的组合。单个Cortex-A7处理器的能源效率是ARM Cortex-A8处理器的5倍,性能提升50%,而尺寸仅为后者的五分之一。
联发科的MT6589手机处理器采用的是4核Cortex-A7架构,它曾被用在红米、中兴U956、华为G520等手机上。不过目前手机性能要求更高,所以Cortex-A7架构处理器的应用场景已转移至低功耗嵌入式设备上,如可穿戴设备,IoT节点等。 i.MX6系列处理器有Cortex-A9和Cortex-A7的不同型号,需要根据具体的应用场景进行选择。
NXP针对MCU(微控制器)的应用场景,推出了i.MX RT系列跨界处理器,该系列下又包括i.MX RT1020、i.MX RT1050及i.MX RT1060等子系列芯片。所谓“跨界”,是指它自身的定位既非传统的应用处理器也非传统的微控制器。
它在i.MX6的MPU(应用处理器)平台之上把其Cortex-A内核换成Cortex-M内核,使得它具备了应用处理器的高性能及丰富的功能,又具备传统微控制器的易用、实时及低功耗的特性。
如果大家觉得学习Linux开发太过复杂,可以先学习一下i.MX RT系列微控制器的应用,因为除了内核,在外设等方面可以说是完全一样,而开发i.MX RT系列微控制器的应用与传统MCU无异,熟悉了i.MX RT系列芯片之后,基本可以跳过i.MX 6裸机程序开发的环节,再学习i.MX6时,仅专注于Linux相关知识即可。
针对i.MX RT系列芯片应用,野火电子提供了非常详细的教程,覆盖裸机至实时操作系统及LwIP应用的教程:
对于学习Linux依然心怀忐忑,希望学习MCU过渡的读者,这些是非常适合的教材。具体资料下载地址请参见链接: https://ebf-products.readthedocs.io/ 。
(图片来源:周星驰 电影《功夫》)
(图片来源:周星驰 电影《功夫》)
本章主要讲解Linux系统的基础使用,包括系统的一些基本概念、安装以及日常应用。
Linux系统由Linus Torvalds (林纳斯·托瓦兹)于1991年发布在新闻组的内核发展而来,由于它在发布之初就免费和自由传播,支持多用户、多任务及多线程,且兼容POSIX标准,使得它支持运行当时主流系统Unix的一些工具软件,吸引了众多的使用者和开发者,逐渐发展壮大至今。
关于Linux系统的发展历史,建议阅读其作者Linus本人的自传《Just For Fun》一书。
当我们说Linux系统时,其含义往往是指采用Linux内核的操作系统。Linux内核负责控制硬件、管理文件系统、进程管理、网络通讯等,但它本身并没有给用户提供必要的工具和应用软件。
由于Linux内核本身是开源的,所以一些人和厂商在其规则之下,基于Linux内核搭配各种各样系统管理软件或应用工具软件, 从而组成一套完整可用的操作系统,见下图。我们称这样的系统为Linux发行版(distribution)。 完整的Linux系统就如同汽车,Linux内核构成了最为关键的引擎,不同的发行版就类似使用相同引擎的不同车型。
Linux系统的完整构成
人们制作发行版通常用于特定的用途,构建哲学不一,侧重点有所不同,因而Linux发行版可谓百花齐放。 其中以Debian、Suse及Fedora派系的发行版最为常见。对于基础用户来说,常常会困惑于安装某些软件时, 软件的安装帮助会针对不同派系的Linux给出不同的安装指令,这实际是由于不同Linux派系之间使用不同的包管理软件(可理解为使用不同的软件商店), 这无伤大雅。常见的Linux发行版关系见下图。
常见的Linux发行版关系图
对于初次接触Linux的用户,建议只要了解到这些都是Linux系统,而且目前我们的开发主机要用的是Ubuntu即可。 至于在开发板上运行的Linux系统,也可以理解为这是我们针对特定板子而定制的Linux发行版。
Debian派系下主要包含Debian、Ubuntu等发行版。
Debian的特色在于其海量的软件支持和apt-get软件包管理系统,而且其支持的硬件平台非常全面, 包括x86、AMD、MIPS、ARM、POWERPC等。
Ubuntu衍生自Debian,由于其易用性,可以说是最成功的Linux桌面版, 且它的成功已经开始漫延至其服务器版本,目前还推出了Ubuntu Core版本针对物联网等小型设备领域, 非常有发展前景。本书将采用Ubuntu作为开发主机的系统环境。
Debian和Ubuntu官网有非常丰富的使用教程,而且中文支持也很好, 推荐初学者多多浏览其中的内容,尤其是Debian。
Debian官网:https://www.debian.org
Ubuntu官网:https://ubuntu.com
Fedora派系下包含Fedora、Red Hat Linux、Red Hat Enterprise(RHEL)、CentOS等发行版。
Red Hat Linux是由Red Hat(红帽)发行的个人版本Linux,现已停止开发, 他们转而开发主要应用于服务器领域的Red Hat EnterpriseLinux(RHEL), 即红帽企业版Linux。使用RHEL的好处是获得安全稳定的技术支持以及企业级的保证, 这正是众多服务器应用场景的核心需求,红帽公司也正是依靠提供这些服务成为了最赚钱的Linux公司。 现红帽公司已被IBM收购。
Fedora发行版是由社区基于RHEL构建的,由Red Hat公司赞助,它大胆采用和验证最新的技术, 部分经验证的技术会被加入至RHEL。因而Fedora与RHEL是被互惠互利关系。 从另一个角度看,Fedora也被认为是RHEL的小白鼠版本。
CentOS全名为Community Enterprise Operation System, 即社区企业操作系统,它由红帽遵循开源协议公开的RHEL源代码构建而成, 它们的区别在于CentOS提供免费的长期升级和更新服务,使用CentOS相当于使用RHEL而不寻求红帽的技术支持, CentOS在我国的小型服务器领域应用非常广泛。
SUSE派系下包含SUSE、SUSE Linux Enterprise Server(SLES)、openSUSE等发行版, 它们的关系类似于Fedora, Red Hat Enterprise Linux(RHEL) 和CentOS的关系。 相对RedHat专长x86架构的计算机来说,SUSE在诞生之初就瞄准大型机,所以SUSE在大型服务器领域占有一席之地。
由于军政系统对信息安全要求严格,我国基于Linux内核构建了中标麒麟、优麒麟、银河麒麟等发行版, 其特色主要在于自主、风险可控。
要进行Linux开发,自然少不了一台运行Linux系统的开发主机。从PC上开始使用Linux系统是最好的熟悉方法。
对于熟悉Linux且有多余主机的用户,建议直接采用独立的主机安装系统作为开发环境。而对于入门级用户, 强烈建议在Windows环境下安装VirtualBox或VMware虚拟机软件,然后在虚拟机上安装相应的Linux系统。 在虚拟机上体验Linux系统的好处是没有后顾之忧,觉得不如意就推倒重来,而且依旧可以使用Windows进行其它工作, 也方便在Windows与Ubuntu虚拟机之间进行文件共享。即使是只进行Linux嵌入式开发工作, 也避免不了需要使用Windows下的工具,如后期我们给开发板烧录uboot、Linux内核时, 使用到的NXP官方MFGtools工具时,还是依赖于Windows系统。
虚拟机技术是虚拟化技术的一种,所谓虚拟化技术就是将事物从一种形式转变成另一种形式,最常用的虚拟化技术有操作系统中内存的虚拟化,实际运行时用户需要的内存空间可能远远大于物理机器的内存大小,利用内存的虚拟化技术,用户可以将一部分硬盘虚拟化为内存,而这对用户是透明的。
流行的虚拟机软件有VMware、Virtual Box和Virtual PC,它们都能在Windows系统上虚拟出多个计算机,本书使用的是免费的虚拟机软件Virtual Box, 我们可以去 https://www.virtualbox.org/wiki/Downloads 官网中下载VirtualBox软件,也可以使用我们提供的资料光盘中的软件,进行安装。
下面介绍一下,安装虚拟机软件VirtualBox的全过程:
运行VirtualBox-6.0.2-128162-Win.exe,可以看到的界面,点击“下一步”,见下图。
需要安装的功能,选择默认即可。软件的安装路径,用户可以根据实际情况自由选择,本书选择安装 在E盘,点击“下一步”,见下图。
安装过程,选择软件自定义的功能,这里选择默认即可,点击“下一步”,见下图。
在安装过程中,会提示一个警告,我们可以忽略该警告,点击“是”,继续安装,见下图。
下图中,点击“安装”按钮,开始安装软件。
这样之后,便开始安装VirtualBox软件,静静地等待,软件安装完成。
软件安装成功,点击“完成”,运行VirtualBox,见下图。
本书以Ubuntu 18.04桌面发行版本作为开发主机的主体系统环境,对于后期编 译内核等依赖不同版本系统环境的情况,我们会采用Docker技术创建其它运行环境。
在安装前需要先到Ubuntu的官网下载桌面版的系统镜像, 可在如下址下载得到: https://ubuntu.com/download/desktop ,具体见下图。
或到国内速度较快的清华镜像源下载:https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/18.04.4/ 使用ubuntu-18.04.4-desktop-amd64.iso 镜像即可。
建议学习时使用与本教材相同的版本,例如用16.04或20.04可能会因为环境不一致引起问题,出现这些问题时折腾会非常浪费时间。
以下为使用VirtualBox安装Ubuntu18.04系统的操作步骤。在以下的步骤中,可按照自己使用的电脑参数进行配置
可从以下地址获取VirtualBox软件: https://www.virtualbox.org/wiki/Downloads ,下载后直接安装即可。
运行VirtualBox软件,点击“新建”按钮,来创建一个新的虚拟机,如下图所示。点击“下一步”。
选择内存大小,默认为1024MB,可以根据自己电脑的配置选择,这里选择4096MB,即4GB的内存大小,点击“下一步”按钮。
选择虚拟硬盘,如下图所示,选择“现在创建虚拟硬盘”,点击“创建”。出现如下所示的窗口,选择虚拟硬盘的类型,一般情况都选择VDI,单击“下一步”。 虚拟硬盘的分配方式有两种:一种是动态分配,需要多少用多少,一开始占用小,随着空间需要而增长;另一种是固定大小, 它会直接占用所分配的物理硬盘空间,但是访问速度快。这里我们选择“动态分配”,点击“下一步”之后,就需要我们选择虚拟硬盘大小,默认是10GB,用户可 以根据自己电脑配置和需要进行分配,这里选择100GB(它不会立即占用这么多的空间,根据自己需求设置即可)。最后点击“创建”按钮,这样就创建好了。
点击右侧的“设置”按钮,如下图所示,选择“存储”栏目,然后选择处来设置系统镜像文件, 通过点击处的按钮来选择我们Ubuntu镜像 文件(*.iso)的路径,设置成功之后,如下图所示,点击“OK”,进入下一步。
选择“网络”栏目,将网卡连接方式配置为桥接网卡,如下图所示。
安装Ubuntu18.04系统,点击启动“启动”按钮,启动虚拟机,如下图所示。进入安装程序,如下图所示。
选择语言,此处可以选择英文,中文等语言,这里我们选择 “简体中文”,然后点击图中“install Ubuntu”按钮,进入下一步。
选择键盘布局,如下图所示,点击“继续”。
选择一些软件安装,如下图所示,点击“继续”,进入下一步。
进入如下图所示的界面,由于虚拟机的虚拟硬盘是独占的,我们选择默认的“清除整个磁盘并安装Ubuntu”即可。
点击继续后会弹出提示确认磁盘的分区修改,点击继续即可。
选择时区,在下图的提示界面区域点击我国东侧位置,其下的文本会出现“Shanghai”字 样,选择后系统使用的就是北京时间。
进入如下图所示的界面,在这个界面中输入用户名和密码,设置计算机名称,用户 可以根据自己的喜好来设置。此处设置的用户会默认具有系统管理员的权限,使 用Linux系统时,常常需要使用该密码进行认证,请牢记该密码。
如下图所示,等待安装完成,然后重启虚拟机,输入密码,就可以看到Linux的桌面了,如下所示。
安装完成操作系统后,可给虚拟机安装增强功能,安装后支持双向复制、共享文件、屏幕自动调整分辨率,使用起来更加方便。
安装过程如下:
在虚拟机界面点击“设备/安装增强功能”即可,见下图。
点击安装增强功能后,虚拟机中会插入一个光盘,并会自动启动安装程序,见下图,在弹出的 界面点击运行。若没有自动启动,可手动双击该光盘进行安装。
点击运行后会出现终端界面输出运行提示,最后提示“press return to close this window”时,按回车键退出即可。
重启虚拟机,进入系统后尝试调整虚拟机控制界面的窗口大小,看到虚拟机内桌面根据窗口大小调整分辨率表明安装成功。
设置虚拟机控制选项中的“设备/共享粘贴板”和“设备/拖放”一栏可以设置虚拟机与主机之间的粘贴板和拖放功能。
在未来的学习过程中,我们有时候需要把下载的资料文件放到虚拟机中,或者是需要把虚拟机的资料挪到Windows主机中, 常用的解决方法有很多,如winscp,FileZilla等软件。不过,上述的软件虽然在使用的过程十分快捷方便,但是在安装过程中, 都相当地麻烦,一会需要在虚拟机上操作,一会又要到主机上操作。我们的虚拟机实际上提供了一个强大的功能: 共享文件夹。我们可以通过这个功能,实现主机与虚拟机的文件传输,安装方式以及使用方法也都十分简单。 下面,介绍一下如何开启虚拟机VirtualBox的共享文件夹功能(执行以下步骤时,确保Linux虚拟机处于关机状态)。
新建文件夹,用于Windows主机和Linux虚拟机共享文件夹。用户可以根据实际情况,创建共享文件夹,见下图。
设置虚拟机的共享文件夹,点击下图的标记处,弹出设置窗口,选择“共享文件夹”选项卡(下图的处), 最后点击下图的按钮,添加共享文件夹,进入下一步。
下图中,点击处按钮,新增共享文件夹,在弹出的”添加共享文件夹”窗口, 我们可以看到处有一个下拉箭头,我们选中处,来选择我们刚刚新建的文件夹。 到这里之后,我们就完成了文件夹路径的设置。我们仍然需要让虚拟机启动的时候,自动挂载共享文件夹, 见下图。选中“自动挂载”选项,在处填入共享文件夹的挂载点, 这里我们建议初学者使用我们提供的路径:/home/用户名/ebf_dir 用户名需要根据用户安装系统时,输入的用户名。 本书使用的embedfire,因此,我们输入的路径为“/home/embedfire/ebf_dir”,最后点击“OK”按钮即可完成设置,见下图。
启动虚拟机,我们就可以看到我们的共享文件夹了,见下图。
单击鼠标右键,左键点击“打开终端”,见下图。
出现如下图所示的窗口,输入命令:
sudo usermod -a -G vboxsf 用户名
本机的用户名是embedfire,因此,输入命令“sudo usermod –a –G vboxsf embedfire”,见下图。
打开之后,这里为了更好地说明,因此在Windows下新建一个普通的txt文档,我们可 以看到Linux也可以对该文档进行操作。
注意 ,共享文件夹它是在Windows也是在Linux下的文件夹,因此我们不要在Linux直接操作共享文件夹的 文件,而是应该将它拷贝到完全属于Linux的地方,比如可以在Linux的桌面上创建一个文件夹, 命名为“work_dir”,然后通过cp命令或者直接复制粘贴的方式将共享文件夹的文件拷贝到这个 “work_dir”工作区域文件夹中。
Ubuntu系统安装好后,请随意体验一下Ubuntu系统,看看能用它做些什么日常操作。
它自带有浏览器,音乐播放器以及一些与Office功能类似的办公软件,如果安装的是中文版, 中文输入法也会默认被配置好。建议使用打开浏览器看看自己的常用网站,打开系统的文件夹新建文件随便记录一些内容, 甚至安装一下Steam游戏平台,看看能玩什么游戏。对于与Windows系统的差异,如不能使用MCU的开发软件Keil等, 不能用Adobe的PS等软件,在这些方面就不要去强求和折腾。现在国产软件开始对Linux重新重视了起来,腾讯QQ也于2019-10-24回归Linux了。
下面我们以Ubuntu下使用gedit编辑器编写文件为例,让大家去熟悉操作系统。 在Ubuntu桌面的左下角有个应用软件列表按钮,点开后可看到系统中包含的应用,如下图所示。
上图中的“文本编辑器”即是Ubuntu系统自带的gedit编辑器,直接点击后打开可以输入文字, 它的使用就类似Windows系统自带的记事本软件一样。
如果安装Ubuntu系统时选择了中文支持,那么系统安装后就自带拼音输入法, 其设置位置在桌面状态栏的“zh”图标中,点击后可 选择汉语拼音输入法,如下图所示。
在后面我们使用命令行的时候,建议直接把输入法关闭掉,即重新点击输入法设置的图标,把它选择回“zh”即可。
输入完内容后点击编辑器右侧的保存按钮,它会弹出选择文件保存位置的弹框,如下图所示。
可以看到它默认的保存位置是“主目录embedfire”,这个是用户自己的目录, 如果你选择其它位置,有可能会因为没有权限而无法保存。选定好存储位 置并输入文件名称后,通过保存按钮可保存文件。
保存关闭文件后,点击桌面任务栏的文件浏览器图标,可以打开到刚刚文件存放的目录, 查找到该文件,如下图所示。
不同的Linux发行版安装应用软件的方式不尽相同,Ubuntu系统自带了软件中心, 使用它可以非常方便地安装和卸载各种软件。
在桌面的任务栏有“Ubuntu软件”图标,如下图所示,点击后可以打开软件中心。
我们可以尝试安装“2048”小游戏。打开软件之后,点击搜索的按钮(下图中的框框处), 输入“2048”,如下图所示,点击安装框框处的“2048”游戏。 未修改软件源前下载速度可能非常慢,不想体验可以直接点击取消安装。
目前Ubuntu软件中心采用Snap软件市场来安装软件,暂时还没有国内的镜像下载源, 所以下载可能需要花比较长的时间。如果不想体验可以直接点击取消安装。
对于刚刚从Windows使用者切换到Ubuntu的用户,觉得最不习惯的地方可能就是文件目录的差异了,但实际上这只是使用习惯导致的,它们有着非常多的共同点,可以对比学习。
当尝试使用gedit等编辑器保存文件时,系统默认通常会先打开个人用户的“家”(home)目录,建议在通常情况下个人相关的内容也是保存在该目录中,因为其它目录大都是系统相关的,使用时容易导致混乱,而且需要相关权限。
点击Ubuntu系统侧栏的文件图标,如下图所示,可以打开系统的文件资源管理器。
打开后可以看到当前用户的主文件夹目录,也称为个人的“家”目录,“home”目录,它与Win10系统的个人目录非常相似,具体见下图。
不过按照大多数人使用Windows的习惯,通常会另外新建磁盘来专门存储不同的内容,如D、E、F、G编号分别为软件盘、工作资料盘、游戏盘、视频盘等。而当我们希望在Ubuntu下尝试复制这种习惯时,发现它并没有列出众多的磁盘,它所有的内容都位于根目录下。
根目录是Linux下所有文件和目录的起点,它的路径用斜杠符号“/”来表示。如下图所示,通过点击文件浏览器的“/其他位置/计算机”可以查看到整个Ubuntu系统的根目录内容。
打开目录后,可以查看到Ubuntu系统根目录的内容,如下图。
也就是说,上图中这些文件或文件夹都位于“/”目录下,而它们的路径分别为“/bin、/boot、/cdrom、/initrd.img”等。
特别地,前面说明的家目录(个人目录)路径为“/home/用户名/”,见下图,图中的例子目录是 /home/embedfire 。 也就是说,在Ubuntu系统下,用户的个人目录都在“/home”下, 并且按照用户名命名,如果系统下有多个用户A、B、C并且它们都有个人目录的话, 那么它们的个人目录路径默认就是“/home/A”,“/home/B”,“/home/C”。在这方面, 跟Windows系统是类似的,在Windows系统下,个人目录默认是“C:/Users/A”,“C:/Users/B”,“C:/Users/C”。
对于Linux开发者来说,必须要了解根目录的内容,这也是大部分人觉得Linux的不友好之处。 如果我们把/home的个人目录排除掉,实质上Linux的根目录与Windows系统C:/Windows目录的功能类似, 都是系统核心的文件,只是对于Windows用户通常不需要了解系统文件目录罢了。 如果仅把Linux系统用于普通的桌面应用,实际上也不需要多么了解它的根目录内容。
但是当我们利用Linux系统进行开发或用于服务器时,一般需要给系统安装各种软件工具, 又或者需要对系统和工具进行配置,常常不可避免地要修改根目录下的文件内容。如软件工具默认安装在/usr/bin目录, 软件工具的配置文件可能位于/etc目录,甚至系统的日常使用如插入U盘或光盘, 又发现它们不会像Windows有独立的盘符可以访问,而是默认挂载在/media或/mnt目录下。
整个Linux系统有且只有一棵从根目录开始的目录树,如下图所示。
所以如果一个计算机中如果有多个硬盘,也不会呈现出Windows下的C、D、E盘的结构,强行复制Windows下习惯的话,可以在根目录下创建C、D、E目录, 然后把磁盘C、D、E挂载在/C、/D或/E目录下,即它们仍然从属于“/”根目录,不过在Linux下通常不会这么用。
目录树只是一个管理上的概念,它本身并不跟硬件挂钩的,例如这些文件之所以是存储在磁盘中,是因为在安装系统时, 已经把整个根目录“挂载”在了磁盘上。所谓挂载就是把存储器的分区与某个目录对应起来,对该目录进行访问时, 相应的操作会被映射到其挂载的存储器分区,而这些存储器包括磁盘、光盘、U盘、NAND FLASH等。
给电脑插入U盘,系统会自动把U盘挂载在“/media/用户名/”目录下,打开该目录即可访问U盘进行读写, 另外,在桌面也会看到一个U盘的快捷方式,通过该快捷方式访问的也是同样的目录。使用VirtualBox虚拟机时,要注意把U盘分配到虚拟机,如下图。
不同的发行版对根目录的理解不同,但它们大都遵守文件层次标准(FHS, Filesystem Hierarchy Standard),所以根 目录下的各个子目录内容和功能大致如下表所示。
根目录的内容:
目录 | 目录放置的内容 |
---|---|
bin | 存放系统命令的目录,如命令cat,cp,mkdir |
boot | 存放开机启动过程所需的内容,如开机管理程序grub2 |
dev | 所有设备文件的目录(如声卡、硬盘、光驱) |
etc | 系统的主要配置文件 |
home | 用户家目录数据的存放目录 |
lib | 存放sbin和bin目录下命令所需的库文件 |
lib32/lib64 | 存放二进制函数库,支持32位/64位 |
lost+found | 在EXT3/4系统中,当系统意外崩溃或意外关机时,会产生一些碎片文件在这个目录下面,系统启动fcsk工具会检查这个目录,并修复已损坏的文件。 |
media | 用于挂载光盘,软盘和DVD等设备 |
mnt | 同media作用一样,用于临时挂载存储设备 |
opt | 第三方软件安装存放目录。 |
proc | 进程及内核信息存放目录,不占用硬盘空间。 |
root | root用户的家目录 |
run | 是一个临时文件系统,存储系统启动以来的信息。当系统重启时,这个目录下的文件应该被删掉或清除。 |
sbin | root用户使用的命令存放目录 |
srv | 一些网络服务所需要的数据文件 |
sys | 同proc目录,用于记录CPU与系统硬件的相关信息 |
tmp | 程序运行时产生的临时文件存放目录 |
usr | 系统存放程序的目录,类似于在windows下的文件夹programefiles |
var | 存放内容常变动的文件目录,如系统日志文件 |
下面我们对根目录下的内容进行详细说明,在阅读这些说明时,请亲自打开对应的目录查看,以建立初步印象。
/bin目录是/binary的缩写,它包含众多普通用户可用的命令。而命令的本质就是可执行程序,即二进制bin文件。熟悉Linux命令后, 回头再来本目录看看,会发现ls、cp、cat等命令,都可以在此处找到,如下图。
/sbin目录是/system bin的缩写,它的功能类似/bin ,不过它存储的一般是系统程序,一般需要使用管理员权限才能使用。 如显示系统已加载的模块命令lsmod、对存储器分区进行格式化的mkfs等。
/etc目录是/etcetera的缩写,据说原始的Unix设计是在该目录存放些零碎的内容,但现在该目录现在已发展成存放系统的各种配置文件, 非常重要。如用户信息文件/etc/passwd,系统初始化文件/etc/rc等,系统依据这些配置运行。在给系统安装某些软件或服务后, 常常需要修改/etc目录下的文件进行配置。
/root是超级用户的目录,在Ubuntu下默认为空。
/home即前面介绍的家目录。
/lib目录是/library的缩写,根文件系统上的程序所需的共享库,存放了根文件系统程序运行所需的共享文件。 如C语言标准库,这些文件包含了可被许多程序共享的代码,以避免每个程序都包含有相同的子程序的副本, 故可以使得可执行文件变得更小,节省空间。如代码A和代码B都使用到C语言标准库的printf和malloc函数, 那么它们就可以共用文件系统上的C库内容,代码A和代码B自身就不需要把C库的这部分内容添加到自己发布的程序包中了。 关于这部分在GCC章节的静态/动态编译将会有讲解。
/dev目录存放了设备文件,即设备驱动程序,用户通过这些文件访问外部设备。 比如,用户可以通过访问/dev/mouse来访问鼠标的输入,就像访问其他文件一样。
/proc目录通常包含了内核导出到用户空间的内核信息,通过访问该目录下的文件可以查看这些信息。
与/proc目录类似,/sys目录用于把内核的设备驱动导出到用户空间,可通过访问sys目录及其下的文件,来查看甚至控制内核的一些驱动设备。
/tmp目录存放程序在运行时产生的信息和数据。但在引导启动后,运行的程序最好使用/var/tmp来代替/tmp,因为前者可能拥有一个更大的磁盘空间。
/boot目录存放引导加载器(bootstrap loader)使用的文件,如lilo,核心映像也经常放在这里,而不是放在根目录中。 但是如果有许多核心映像,这个目录就可能变得很大,这时使用单独的 文件系统会更好一些。
/mnt目录是系统管理员临时挂载(mount)文件系统的安装点。/mnt下面可以分为许多子目录, 例如/mnt/dosa可能是使用 msdos文件系统的软驱,而/mnt/exta可能是使用ext2文件系统的软驱,/mnt/cdrom光 驱等等。
/media目录通常是一些自动挂载的设备目录,如光盘和U盘,部分系统会自动挂载到这个目录下, 然后通过自动挂载的目录可以访问对应的设备。
曾经的 /usr 还是用户的家目录,存放着各种用户文件 —— 现在已经被 /home 取代了(例如 /usr/someone 已经改为 /home/someone)。 现代的 /usr 只专门存放各种程序和数据,用户目录已经转移。虽然 /usr 名称未改, 不过其含义已经从“用户目录”变成了“unixsystem resource”(Unix 系统资源)。值得注意的是,在一些 unix 系统上, 仍然把 /usr/someone 当做用户家目录,如 Minix。
在Linux下,我们看到的一切都是文件,主要包括如下类型。
如文本文件,bin文件等。
可执行文件包括脚本和应用程序,这些文件可被系统加载运行,类似Windows下的bat脚本、exe程序文件等。
链接文件分为硬链接和软链接:
在Linux下目录也是文件。
硬件设备也是文件,通过打开对应的设备文件可以初始化设备,部分设备还可以通过读写设备文件实现对硬件的控制。
在Windows下习惯通过文件的后缀名来判断可以使用什么软件打开对应的文件,而Linux下没有这样的要求, 便Linux下为了容易区分和兼容用户使用Windows的习惯,我们还是会用扩展名来表示文件类型。举例如下:
在早期的Windows操作系统,如Windows 95 和 Windows XP,都是单用户操作系统。 所谓的单用户操作系统,就是说在同一时间,只能由一个用户独自享用系统的全部硬件和软件资源。 我们现在所使用的win7、win8以及win10都是多用户操作系统,与单用户操作系统恰恰相反, 它支持多个用户能够同时访问和使用同一台计算机的全部硬件和软件资源,
在众多用户中,其中的一个用户administrator具有管理其他用户账号和计算机的全部资源的权限。 我们在安装软件的时候,经常会看到“要以管理员身份运行该软件”,又或者是如下图,实际上就是要求我们给予程序一些管理员的权限。
Linux操作系统,同样也是多用户操作系统,其中具有管理其他用户和计算机的全部资源的用户, 称为root。前面提及过安卓系统,实质上也是基于Linux,安卓手机上常常提到的root权限,也就是获取最高的权限, 就跟电脑获取超级管理员的权限是一样的。
在Linux中,每个用户都有一个特定的编号——UID,用于标识一个系统用户。Linux将标号0分配给root用户的uid, 它可以分配给每个用户不同的权限,因此每个用户可进行的操作也不同。
我们可以通过id命令来查看当前用户的UID值(关于如何使用命令在下一章介绍,此处先了解):
id
上图中的gid用于标识当前用户所在的分组(Group),每个用户可以对应多个分组。 就好像学校里面有音乐社,动漫社,文学社等社团,每个学生可以去参加多个社团,这样才能够接触到各种各样有趣的东西。 Linux系统拥有多个分组,每个用户分组就相当社团,用户如果是多个用户组的成员,就可以访问其他分组对应的文件, 前提是该分组的文件允许其他用户访问,这就需要了解另一个知识点:文件权限。
在Windows系统中我们经常接触的文件属性,无非就是以下两种属性:只读、隐藏。
从字面上的意思,我们也很好理解。具有只读属性的文件,我们不能对文件的内容进行修改。而具有隐藏属性的文件,我们一般情况下是看不到的。
在Windows上,通过选中文件,然后右键调出菜单,就可以看到“属性”选项, 那如何在Linux查看一个文件的属性?其实,查看方法和Windows相差无几, 同样也是先选中一个文件,右键可以看到下图右侧的菜单。我们通过最下面的“属性”选项来查看某个文件的具体情况,如下图所示。
除此之外,关于Linux文件权限,还需要分三种情况:文件拥有者(owner),分组成员(groups)以及其他分组成员(other)。 如本示例中的文件允许文件拥有者embedfire对该文件的内容进行读写操作, 而对于embedfire分组以及其他分组的用户则只能阅读该文件,并不能对该文件进行修改。 如果我们想修改其他分组的文件,我们可以修改该文件分组所拥有的权限。
在后面学会使用命令行后,我们可以通过chmod命令在终端快速地修改文件的权限。
使用桌面Ubuntu的一大好处是它的对用户很友好,日常的基础应用都可以通过它的图形界面完成, 但界面做得再完善,还是有很多操作无法通过界面完成的,因为绝大部分程序本身根本就不提供界面, 或者界面只提供一小部分常用操作。但是几乎所有的程序都能通过命令行来调用运行, 并且通过命令行提供丰富的操作选项。尤其是做开发时,不要总想着有IDE,有当然好, 但我们要接受只能使用命令行的处境,实际上,用多了就习惯了。
Linus Torvalds(林纳斯)在其自传中提到,他在编写Linux操作系统内核的时候, 首要目标就是让Linux系统能兼容正常运行Unix下的Shell程序。因为Shell是命令行解释器, 它的Linux系统若能兼容Unix的Shell,那么大部分类Unix的程序也很容易做到兼容了。
在早期的Unix系统与用户就是通过Shell进行交互的,如下图所示,Shell对外接受用户输入的命令, 对内通过“系统调用”传递给内核,内核执行操作后把输出通过Shell呈现给用户,也就是说, Shell就是一个中间人。而Shell的英文原意“壳”,也是为了把它与内核区分开来。
在平时的交流中,有时我们会说打开Shell、终端(Terminal)或控制台(Console), 严格来说它们实际上不是同样的东西,但只要明白,当我们说打开Shell、终端或控制台的时候, 通常就是为了使用命令行控制系统。它们的严格区分如下,了解下即可:
实际上,在Windows也有终端,下图是类似于Windows操作系统的cmd程序,而在Ubuntu的命令行终端如下图所示。
如上图,打开终端后,我们可以看到终端本身显示了一行字符,而且按回车后会重复出现:
embedfire@dev:~$
实际上这行提示符分成以下几个部分:
废话少说,请亲自尝试在终端中输入如下命令,注意如果使用了中文输入法的话,要记得把它切换回英文模式。 另外,在以下命令中的波浪号“~”也是英文符号,还要注意终端中所有的内容都是区分大小写的:
1 | # 在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
---|---|
2 | # 在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
3 | # 从下面开始是你要在终端中输入的命令(不包括#号后的内容): |
4 | |
5 | cd /home # 切换到/home目录 |
6 | pwd # 显示当前目录 |
7 | cd ~ # 切换至~目录 |
8 | pwd # 显示当前目录 |
9 | ls # l是字母L的小写,不要把l输入成数字1或字母i的大写 |
10 | ls -l # 同上,两个l都是字母L的小写 |
每行命令输入后按回车,Shell就会对输入的命令进行解释,执行后输出,运行结果如下所示。
以上各行命令的意义如下:
通过以上的一些命令示例,我们大致可以归纳一下命令的格式:
command [-options] [argument]
命令的组成一般分三部分,每部分之间使用空格隔开,说明如下:
在命令格式中,使用“[ ]”括起来的内容表示它不是要求必需的,例如前面使用时cd命令时没有带选项, 使用pwd命令不带选项及参数。
Linux下系统本身就支持数不清的命令,不同的命令又带不同的选项, 输入的参数往往又有不同的意义,除了丢下一句“用多了就会记住”这不负责任的说法外,使用命令其实还是有一些门道的。
每个命令都会带有一个“-h” 或者“–help”的参数,可以用来打印一些帮助说明。 比如,如果现在不知道ls的选项a有什么用法,那么就可以执行下面的命令:
ls --help
从上图中圈出来的地方,可以知道参数a可以只列出隐藏的内容。现在执行命令:
ls –a
从上图中可看到该执行后比直接用“ls”命令多列出了很多以“.”开头的内容, 在Linux下以“.”开头命名的文件或目录默认为隐藏文件,而ls的“-a”选项可以把它们显示出来。
补充说明一下,帮助信息中的“-a”后面还有“–all”参数,这两个参数是等价的,只不过“–all”会比“-a”好记。
有些时候我们甚至连命令的全称都想不起来,这时可以用到命令行的自动补全功能。就是键盘上神奇的“Tab”键。
假如我们知道有个命令是以“whic”开头,但想不起全称, 那么我们可以在终端输入“whic”然后按一下“Tab”键(键盘上字母Q的左边),它会自动补全命令为“which”。
如果我们只记得命令是以“wh”开头的话,按一下“Tab”键发现它没反应(如果接入了耳机可以听到一下提示音), 这时我们尝试按两下“Tab”键,如下图所示。
终端输出了好多以“wh”开头的命令,如which,who,whoami等。
所以按一下“Tab”键时如果只有一个匹配的内容时它会自动补全,按两下“Tab”键则会列出所有的匹配项。
“Tab”键除了用来补全命令名,还可以自动补全路径,如我们使用cd命令输入“/home”参数时, 先输入“/ho”然后按下“Tab”键,它会把“/ho”自动补全为“/home”路径名,如下图所示。这在使用命令行时是频繁使用的技巧,能减少我们的输入,而且不容易出错。
如果对命令只记得大概,也可以大致地乱敲一通,如果运气好, 按下回车后如果终端找不到这个命令时它会输出类似命令的提示,我们可以根据提示来了解。 我们输入“whihc”回车后如下图所示,它提示我们找不到“whihc”命令,并询问我们想输入的是不是“which”。
在应用中我们有时会想要中止命令的执行,或者命令输入到一半的时候觉得输错了不想继续, 这时我们都可以通过“Ctrl”+“c”的组合键来结束。
如在终端输入:
# 在后面的说明中,#号表示注释,它后面的内容不要输入到终端中
ping 127.0.0.1 #尝试ping测试自己的网络地址127.0.0.1
以上ping命令会持续输出,按下“Ctrl”+“c”组合键来结束
又例如,我们在终端输入了以下内容,然后又不想让它执行,使用删除键一个 个字符删除很麻烦,也可以通过“Ctrl”+“c”的组合键来取消:
ls adfadfadsfadsfa
输入以上命令后不想运行以上命令,按下“Ctrl”+“c”组合键来结束
命令究竟是什么,当我们敲下命令“ls”后,Shell究竟做了什么事情。在 《Linux文件目录/bin目录》 小节中提到, /bin目录下包含了很多命令,如下图所示,可看到ls、lsblk、lsmod、mkdir等命令程序。
在终端中,我们使用which命令可以查看指定命令的路径,如查看ls、pwd、cd命令:
1 | # 在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
---|---|
2 | |
3 | which ls # 查看使用的是哪个ls命令 |
4 | which pwd # 查看使用的是哪个pwd命令 |
5 | which cd # 查看使用的是哪个cd命令 |
从上图中可了解到ls命令实际是/bin/ls程序,pwd命令实际是/bin/pwd程序,而which cd命令没有输出, 因为cd命令是Shell自己内部的程序。
我们在Shell中输入ls命令与输入/bin/ls的作用是一样的,当我们输入Shell时,它会到预定的目录下查找有没有该程序, 如果有就使用命令选项及参数调用该程序执行,并把程序的输出再呈现出来。而这个预定的目录我们可以通过如下命令来查看:
echo $PATH # echo是输出命令,而"$PATH"是一个变量,表示输出变量内容
“ P A T H ” 是 终 端 使 用 的 路 径 环 境 变 量 , 它 使 用 “ : ” 进 行 分 隔 , 表 示 S h e l l 将 会 在 这 些 路 径 下 寻 找 命 令 程 序 , 在 其 中 我 们 可 以 看 到 / b i n 路 径 。 也 就 是 说 , “ PATH”是终端使用的路径环境变量,它使用“: ”进行分隔,表示Shell将会在这些路径下寻找命令程序, 在其中我们可以看到/bin路径。也就是说,“ PATH”是终端使用的路径环境变量,它使用“:”进行分隔,表示Shell将会在这些路径下寻找命令程序,在其中我们可以看到/bin路径。也就是说,“PATH” 路径环境变量让我们输入命令时省去了输入完整路径的麻烦, 而命令的本质大都是在文件系统中的一些应用程序。
下面我们列出一些常用命令的讲解,请都亲自在终端里尝试运行一下。
cd命令是change dir的简写,它可以把终端当前所在的路径切换至目标路径。该命令的格式如下:
cd [目录名]
格式说明中 “目录名”就是要切换至的路径,若目录名称省略,则切换至当前用户的 home 目录 。
除某些有特殊要求的应用程序,Linux自带的所有命令在终端运行时,“目录名”都可以使用绝对路径或相对路径。
例如当前终端所在的路径为“/home/embedfire”,那么以下两个命令是等价的:
它们都表示切换至“/home/embedfire/test”目录,这其中的“test”就是相对路径,而“/home/embedfire/test”是绝对路径。
特别地,我们需要知道目录的如下表示:
我们尝试执行以下命令,进行目录切换实验,注意其中的embedfire是当前的用户名,具体请根据自己的用户名进行修改。
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | cd / # 切换至根目录 |
3 | ls # 列出当前目录的内容(根目录) |
4 | cd - # 返回至上一次的目录(家目录) |
5 | cd … # 切换至上一级目录 |
6 | ls # 列出当前目录的内容(home目录) |
7 | cd embedfire # 切换至embedfire目录(请把embedfire换成自己的用户名) |
注意以上命令中,命令名cd与路径名之间是有空格的,实际上包括以后使用的所有命令中, 命令名,命令选项以及命令参数之间都是要有空格分隔开的。
上图中执行切换至根目录的命令后,命令行提示符中的目录就变成“/”,且可以用 直接用ls列出了当前的文件,最后再通过“-”参数切换回了用户的家目录。
mkdir命令是make directory的简写,它可以在文件系统中创建一个新的目录。其命令格式如下:
mkdir [-p] 目录名
命令格式中的“目录名”就是要创建的目录路径,“-p”选项可以不输入,若使用了“-p”选项, 当创建的目录名包含的上级目录不存在时,它会自动创建所有不存在的目录。
我们尝试执行以下命令:
#在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 | |
ls # 列出当前目录的内容,此时没有testdir目录 | |
mkdir testdir # 创建目录testdir | |
ls # 列出当前目录的内容,发现多了testdir | |
mkdir other/test # 创建目录other/test,因为other不存在,报错 | |
mkdir -p other/test # 使用 -p 选项创建目录other/test | |
ls # 列出当前目录的内容,发现other目录 | |
ls other # 列出other目录的内容,发现test目录 |
touch命令可以创建不存在的文件,或者touch通过参数修改目录或文件的日期时间,就是摸一下,更新它的时间。
它的命令格式如下:
touch 文件名
尝试执行如下命令:
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | touch helloworld # 在当前目录下创建一个名为helloworld的文件 |
3 | ls # 显示当前目录下的内容 |
使用touch命令,新建一个helloworld的文件,然后使用ls命令来查看文件是否被创建,执行结果如下图所示。
ls命令是list的简写,在前面我们已经频繁使用,它是Linux下最常用的指令, 功能为显示指定目录下的内容(文件及子目录) ,还可以查看文件大小,修改日期等等信息。
ls命令格式如下:
ls [选项] [目录]
当“目录”参数省略时,它会列出当前目录的内容。
除了基本的显示,ls命令还有以下常用选项:
尝试执行如下命令:
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | ls # 列出当前目录的内容 |
3 | ls -a # 显示当前目录下的所有内容 |
4 | ls -A # 显示当前目录下除“.” 及 “…”外的所有内容 |
从上图可以看到,缺省参数下的ls命令只能列出非隐藏的文件或者文件夹, 而ls –a或者ls –A这两条命令会把所有文件,包括隐藏文件在内都罗列出来。 在linux中,以点“.”开头命名的文件在系统中被视为隐藏文件。不过ls –a 和 ls –A这两个命令的执行结果, 区别在于是否列出“.”和“…”。
除此之外,在终端上罗列出来的文件是白色的字体,而文件夹是淡蓝色的字体,以此来区分文件和文件夹。
特别地,有时我们需要查看文件的详细信息,可以使用“-l”参数,我们尝试执行以下命令:
ls -l
可以看到如下图的结果 参数l的执行结果的结果,得到当前目录下所有文件所占用的空间总和以及一个7个字段的列表。
各个字段的说明如下:
第一字段:文件属性
文件属性共有十个字符,第一个字符代表文件的类型,字符“-” 表示该文件是一个普通文件;字 符“d”是dirtectory(目录)的首字符,表示该文件是一个目录。
后面的九个字符,每三个为一组,分别表示文件拥有者 的权限、文件所属组拥有的权限以及其他用户拥有的 权限。字符“r”代表的是读(read)权限,字符“w”代表的 是写(write)权限,字符“x”代表的是执行(execute)权限。
第二字段:链接占用的节点/子目录的个数
第二字段的含义,主要取决该文件的类型,如果是文件的话,则表示该文件所具 有的硬连接数。某个文件的第二字段如果等于1的话,代表没有其他指向该文件的硬连接。
根据 Linux 系统存储文件的特点,链接的方式可以分为两种,分别是硬链接 和软连接(符号连接)。软链接,类似于Windows操作系统的快捷方式。而硬链 接,则是相当于把该文件复制一份,同时加上自动更新。当我们修改了硬链接文 件的内容,源文件也会被修改。当为某个文件创建硬链接时,该字段的值便会加1。可以使 用ln命令创建软链接和硬链接,当前只要知道有这回事即可,先不要纠结软链接和硬链接的概念。
对于文件夹来说,第二字段则表示该文件夹下有多少个子目录。空文件夹 的话,该值默认等于2,这是因为包含了“.”和“…”子目录。
第三字段和第四字段:文件拥有者和文件所在的组
Linux系统属于多用户系统,每个文件都有它的拥有者。结合第一字段的后九个字 符,一般只有文件拥有者有权利去修改文件。当然,对于root用户有权利 去修改任何文件。以“视频”文件夹为例:
结合下图,进行理解:对于文件拥有者embedfire,它拥有对该文件夹的读、写、执行的权限,对于在embedfire分组的其他成员xiaoming,就只可以进行读、执行的权限。还有位于Other分组的用户xiaohong,也是只有读、执行的权限。
第五字段:文件所占用的空间(以字节为单位)
第五字段表示文件大小,在Linux中,目录是一个特殊的文件。
第六字段:最近访问(修改)时间
第五字段表示文件最近访问的时间,使用touch命令,可以修改文件的第六字段。
第七字段:文件/文件夹名称
cat命令是concatenate的简写,译为串联,即它可以把两个内容串联起来,我们通 常使用它在终端下输出文件的内容进行查看。
命令格式为:
cat 文件名
前面我们使用gedit编辑器保存了一些内容到test123.txt文件上,此处可以使用如下命令把它的内容输出到终端:
cat test123.txt
echo命令的功能是在终端上打印一段文字,也可以把终端 的变量内容打印出来。
其命令格式如下:
1 | echo “字符串” |
2 | echo 字符串 |
3 | echo $变量名 |
使用echo命令时,带双引号和不带双引号的效果是一样 的,使用引号时,要注意用英文符号。
我们尝试执行如下命令:
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | echo “test” # 打印字符串 |
3 | test echo test # 打印字符串 |
4 | test echo $PATH # 打印环境变量 |
5 | PATH echo “$PATH” # 打印环境变量PATH |
在上面看到命令执行后都是输入到终端显示,有时我 们希望把命令执行的结果保存到文件进行分析,这时我们可以使用 输出重定向到文件的控制符“>”或“>>”,其中“>”会直接用输出 覆盖原文件,而“>>”则把输出追加到原文件的末尾。
使用格式如下:
| |
---|---|
1 | 命令 > 文件名 |
2 | 命令 >> 文件名 |
重定向时文件不存在会自动创建。
尝试执行如下命令:
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | echo test > file.txt # 把echo test的输出重定向至file.txt文件 |
3 | cat file.txt # 查看file.txt文件的内容 |
4 | echo abc > file.txt # 把echo abc 的输出重定向至file.txt文件 |
5 | cat file.txt # 查看file.txt文件的内容 |
6 | echo 123456 >> file.txt # 把echo 123456的输出重定向追加至file.txt文件 |
7 | cat file.txt # 查看file.txt文件的内容 |
8 | ls > file.txt # 把ls命令的输出重定向至file.txt文件 |
9 | cat file.txt # 查看file.txt文件的内容 |
上图演示了echo命令和ls命令的输出重定向至文件file.txt中,重定向执行命令后输出不会显示在终端上。
rmdir命令是remove directory的简写,它的功能是删除空的目录。
命令格式如下:
rmdir [-p] 目录名
与mkdir的选项类似,-p可以用来递归删除目录,如果子目录删除后其父目录为空时,也一同被删除。
特别地,rmdir命令只能够用来删除空目录,当删除一个非空目录时,会提示“删除”某某某”目录失败: 目录非空”,所以实际上这个命令用得并不多。
下面我们执行以下命令,来删除我们上面创建testdir目录和其other/test及其子目录。
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | rmdir testdir # 删除testdir目录 |
3 | rmdir -p other/test # 删除other/test目录,若删除后other为空,把other目录也删除掉 |
命令rmdir –p other/test/是删除空子目录test,但由于参数p的作用下,删除了test目录之后, 目录other也为空目录,因此other目录也会被一起删除。假如没有参数p的话, 那么other目录依然会存在,读者可以自己尝试一下。
rm命令是remove的简写,它的功能是删除一个或多个文件或目录。
其命令格式如下:
rm [选项] 一个或多个文件/文件夹名
使用rm命令删除内容时,文件是会被直接永久删除的,它并不会放到回收站中再确认。 所以在使用rm命令前,一定要考虑清楚。 特别时如果你使用的是系统管理员账户或者通过后面介绍的sudo命令获取了系统权限, 那么只需要一句命令就可以实现删库跑路,酿成大祸!
它支持的选项如下:
虽然rm命令使用不当很容易造成严重后果,但不能因噎废食,而且趁我们现在的系统是刚安装的, 没有什么重要内容,在家目录进行操作通常也不会影响到系统的正常运行, 所以大可以放心去运行以下命令进行实验:
#先创建一些试验文件给后面删除
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | mkdir -p ABC/test #创建ABC/test目录 |
3 | ls #列出内容 |
1 | touch a.txt b.txt c.txt d.txt #创建 几个测试文件 |
2 | ls #列出内容 |
先结合前面学习的mkdir和touch命令,在当前目录创建一个ABC目录, 里面包含了一个子目录test还有a.txt,b.txt, c.txt,d.txt,执行结果如下图所示。
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | rm a.txt b.txt #直接删除a.txt b.txt |
3 | rm –i c.txt d.txt #询问式删除c.txt d.txt |
执行上面两条命令的其中一条都可以完成删除任务。当带有参数i时, 则会有询问是否删除文件,如果是,输入y;反之,则输入n。如下图所示, 直接删除了a.txt,b.txt。使用询问式删除时,删除了c.txt,保留了d.txt文件。
前面提到rmdir命令不能删除非空的目录,我们可以使用rm命令配合“-r”选项来完成:
rm –r ABC/
执行以上命令之后,就会把目录ABC以及子目录test,即ABC下的内容统统都删除掉。 因此,为了防止误删文件,使用rm命令时尽可能加上参数i。
执行以下两条命令,比较执行结果的差异:
rm a.txt rm –f a.txt
当使用第一条命令时,会提示“删除失败,找不到该文件”,但是当我们使用参数-f时, 就忽略该提示。这里只是简单介绍一下该参数,日常使用中还是尽量不要使用该参数,以免造成无法挽回的损失。
sudo命令是switch user do的简写,意思是切换用户去做某件事情。
在Linux中,有一个名为root的超级用户。它可以做任何事情,权力越大,责任越大。 因此在日常工作中,若一时没注意输入了错误的命令,可能会导致系统崩溃, 所以在Ubuntu下默认是不能用root用户登录的。但是在很多情况下我们又需要用到root的权限, 如安装某个软件,若使用普通的用户会提示“权限不够”。 这时候我们可以在需要root权限的命令前添加sudo命令,从而使当前用户获得root权限, 并执行其后的命令。所以Ubuntu需要用sudo实际上是提醒我们接下来执行的命令有可能会影响到系统的关键内容, 要小心操作。
sudo命令格式如下:
sudo 命令
使用sudo命令时会提示输入你当前的用户密码,而不是root用户的密码。 请注意,你输入的密码不会显示在终端上,而且终端也不会随着你的输入而显示星号(*)!自信地在键盘上敲入密码,然后按回车即可。
下面我们尝试使用sudo命令在需要root权限的目录进行操作:
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | cd /home # 切换至/home目录 |
3 | touch test.txt # 尝试在当前目录创建test.txt文件 |
4 | sudo touch test.txt # 使用sudo增加权限,创建test.txt文件 |
5 | |
6 | # 输入密码时终端也不会随着输入而显示星号(*),输入完回车即可! |
7 | # 输入密码时终端也不会随着输入而显示星号(*),输入完回车即可! |
8 | # 输入密码时终端也不会随着输入而显示星号(*),输入完回车即可! |
9 | rm test.txt # 尝试删除test.txt文件 |
10 | sudo rm test.txt # 使用sudo增加权限,删除test.txt文件 |
如上图所示,当前用户是embedfire用户,切换至/home目录后,它没有往该目录写入文件的权限, 所以直接用touch命令尝试创建文件时提示权限不够。当我们在touch命令前增加sudo命令, 并输入正确的用户密码后获得了权限,所以文件被成功创建。类似地,当我们直接尝试用rm命令删除文件时, 也会提示权限不足,再增加sudo后即可删除。而且可以发现这时不需要再次输入密码了,也就是说认证成功后能维持一段时间,但是使用命令时,还是要添加sudo操作。
有时我们在执行命令时忘记添加sudo前缀,执行失败提示时才想起要加sudo,这时可以使用“sudo !!”的方式使用sudo权限重新执行上一条命令。
1 | #在后面的说明中,#号表示注释,它后面的内容不要输入到终端中 |
2 | cd /home # 切换至/home目录 |
3 | touch test.txt # 提示没有权限 |
4 | sudo !! # sudo加两个感叹号,重新使用sudo权限执行上一条命令 |
执行过程如下图:
部分用户在使用系统时,会觉得使用sudo命令很麻烦,有时干脆直接切换到root用户去进行开发,这常常会导致各种问题。 例如部分构建工具直接不支持root用户运行,有时我们用了root用户去解压或拷贝工程文件, 一不注意又使用普通用户去运行,这时会因为普通用户没有权限而出错,但找起原因却很浪费时间。 所以我们强烈建议在开发及日常使用时,不要使用root用户。
终端执行各种命令后会保留之前的内容在屏幕上,如果觉得碍眼,可以直接运行clear命令清除:
clear
在终端上,reboot/poweroff命令来控制系统的重启与关机。直接使用如下命令即可:
1 | reboot |
2 | poweroff |
注意:IMX6ULL开发板在使用poweroff命令关机后,需要长按ON/OFF键1~2秒才能正常开机。 这是因为执行poweroff后,芯片的SNVS(电源管理)寄存器进入关机状态。纽扣电池只要持续供电, 那么芯片会一直保持关机状态,直到触发ON/OFF键后才能改变关机状态。(即直接插拔DC电源也无法重启,需要长按ON/OFF按键)
man命令值得我们为它独立一小节来进行说明。
前面只列出了几个常用命令,对于Linux系统来说,这些只不过是九牛一毛。那么多的命令,而且有的命令还有那么多的参数,怎么可能记得住? 除了–help选项外,Linux还提供了一个man命令,可用于查看Linux系统自带的参考手册,该手册包含非常丰富的内容, 甚至在我们进行编程开发时还可以使用它来查看函数的接口。
man命令格式:
man [要查询的内容]
使用起来非常简单,如我们想查看ls命令的说明,直接输入如下命令即可:
man ls
按键盘方向键的“↑”“↓”键可以实现上下切页。按“q”键可以退出手册。
关于man手册本身的使用,可以使用如下命令查看:
man man
从上图可了解到,除了Shell命令外,还可以看到man手册支持共9种类型的内容,如第一章是关于Shell命令, 第二章是系统调用(内核提供的函数)、第三章是库调用(程序库中的函数),如我们可以查看内核函数fork及C标准库函数printf的说明:
1 | man fork |
2 | man printf |
man是按默认顺序来查找的,有时我们要查阅的内容可能在前面的手册出现, 而它不是我们需要的内容,例如前面的C库函数printf ,或者查阅open系统调用函数时, 出现的却是Shell的printf和openvt程序说明:
#直接man open,它会按默认顺序搜索,结果搜索出了openvt的Shell命令说明
man open
在上图中可以看到OPENVT(1)说明页是在第一章节的,与PRINTF(1)类似。
解决这个问题可以通过指定章节号来查询,因为我们要查询的printf是C库函数、 open是Linux的“系统调用”API,所以我们可指定它就在该章节查找,前面的man命令输出中可看到“库调用”属于第3章, 而“系统调用”是属于第2章,所以使用man命令时,我们通过“-s”选项指定它搜索的章节号:
通过-s指定搜索章节的内容,man手册的章节3是“库调用”相关的函数说明:
man -s 3 printf
可以省略-s,使用以下命令是等价的:
man 3 printf
man手册的章节2是“系统调用”相关的函数说明:
man -s 2 open
可以省略-s,使用以下命令是等价的:
man 2 open
在以后的学习中,请养成使用man手册的习惯,它是最便捷和权威的说明书。
在windows操作系统中,我们要想安装某个软件的时候,只要点开相应的exe文件,一直按“下一步”,最后点“完成”, 这样就可以在我们电脑上使用这个软件了。前面我们也提到过,Ubuntu提供了一个软件商店,虽然它也可以提供软件的下载, 并且能够自动安装,但是有些软件并不一定能够在里面搜索得到,那只能以源码的方式来安装软件。采用源码的安装方式, 都需要检测当前的系统环境,设置编译的参数,如加入/剔除某个模块等,这样的安装方式就显得非常的繁琐。
目前,大多数类 Unix 操作系统都提供了一种中心化的机制用来搜索和安装软件,软件开发者先在固定的硬件平台上将需要安装或升级的软件编译好, 然后再将软件的所有相关的文件打包存放在公开的服务器中。用户想要安装某个软件时,通过包的形式进行分发,包提供了操作系统的基本组件, 以及共享的库、应用程序、服务和文档,当用户需要时,可以运行特定的指令来安装。负责这部分工作内容的工具被称为包管理工具, 包管理工具除了安装软件外,它还负责更新已经安装的包。
在Linux操作系统中,最常见的两种包分别是deb和rpm。
在Debian、Ubuntu等Linux发行版中,通常使用deb(debian)形式的软件包,如下图是Vim软件的deb安装包。
若下载了deb软件包,可使用如下命令进行安装,其中xxxx.deb为要安装的软件包的名字:
# 使用dpkg手动安装deb包的命令
sudo dpkg -i xxxx.deb
命令中的dpkg(Debian Packager)是Debian专门开发的包管理工具,它可以用来安装、更新和移除软件, 安装时它需要使用deb类型的软件包。
dpkg是一个底层的包管理工具,主要用于对已下载到本地和已经安装的软件包进行管理。 在它之上的apt(Advanced Package Tool)包管理工具,其功能则更加丰富和方便使用, 使用apt能够自动从互联网的软件仓库中搜索、安装、升级、卸载软件,它会咨询软件仓库, 并能安装软件时的模块及依赖问题。
如果是使用apt工具安装某个软件,直接使用如下命令即可,它会自动下载并安装软件:
sudo apt-get install 软件名
概括起来可以这么理解,deb是软件包,dpkg是手动安装工具,apt是自动安装工具。
类似地,在RedHat,Fedora,Centos等派系的Linux发行版中, 通常使用rpm(RedHat Package Manager)形式的软件包,下图是Vim软件的rpm安装包。
若下载了rpm软件包,可使用如下命令进行安装,其中xxxx.rpm为要安装的软件包的名字:
rpm -ivh xxxx.rpm
命令中的rpm与dpkg的功能类似,同样是主要用于对已下载到本地和已经安装的软件包进行管理。 在它之上的yum(Yellow dog Updater, Modified)包管理工具,功能与apt工具类似, 它会咨询软件仓库,并能安装软件时的模块及依赖问题。
使用yum安装软件的命令如下,同样地,它会自动下载并完成安装:
yum install 软件名
关于这些软件包和工具,总结如下表:
表 软件包和工具
Debian派系发行版 | Redhat派系发行版 | |
---|---|---|
软件包 | deb | rpm |
基础包管理工具 | dpkg | rpm |
上层包管理工具 | apt | yum |
本书使用的Linux发行版是Ubuntu,对应的包管理工具就是apt工具,apt包管理工具包含了如下内容:
使用apt-get工具安装程序的时候,需要你知道应用程序的名字。具体的命令语法:
sudo apt-get install 软件包名
apt-get install会扫描本地存放的软件包更新列表/var/lib/apt/lists/,找到最新版本的软件包, 然后检查软件包依赖关系,找到支持该软件正常运行的所有软件包,并从镜像源地址中下载所需的软件包, 最后解压软件包,自动完成应用程序的安装和配置。
下面带大家来安装一个有趣的命令:sl。运行该命令之后,你的终端里会出现一辆火车在跑,执行以下命令:
可以看到终端会输出很多信息,下面我们把输出信息拆分成三块进行讲解:
上图中的输出信息,apt-get install正读取软件包列表,并且检查软件包的依赖关系,并且列出了所有的依赖文件。
上图则是apt-get install从镜像源http://cn.archive.ubuntu.com/ubuntu中下载所需要的软件, 并且自动解压,完成安装的整个过程。
运行刚刚安装的软件,在终端输入命令:sl,就可以看到下图的画面。
讲了如何安装软件,自然也要知道如何卸载一个软件,具体的命令语法如下:
sudo apt-get remove 软件包名
在执行命令之后,终端会提示是否继续执行删除操作,输入“Y”的话,该软件就和你彻底说拜拜了, 输入“n”的话,则会终止当前的删除操作。
apt-cache是Ubuntu的另一个APT软件包管理工具。通过apt-cache工具 配合对应的子命令,可以实现查找,显示软件包信息及包依赖关系等功能,见下表。
表 apt-cache工具
命令 | 作用 |
---|---|
apt-cache showsrc 软件包名 | 显示软件包的相关信息,如版本信息,依赖关系等 |
apt-cache search 软件包名 | 按关键字查找软件包 |
apt-cache depends软件包名 | 显示该软件包的依赖关系信息 |
apt-cache rdepends软件包名 | 显示所有依赖于该软件包的软件包名字 |
apt-cache show 软件包名 | 显示指定软件包的信息,如版本号,依赖关系等. |
apt-cache pkgnames | 显示所有软件包的名字 |
apt-cache policy 软件包名 | 显示软件包的安装状态 |
例如,可通过如下命令搜索支持ifconfig命令的软件包:
apt-cache search ifconfig
APT包管理工具还包括apt-config工具,用于配置所有的APT工具,但是我们基本上接触不到。 因此,我们只需要重点掌握apt-get工具的用法,对于apt-cache的话,我们只需要大概了解即可。 实际上,Ubuntu开发团队也发现了这个问题,并且给出了有效的解决方法:直接使用apt命令不区分地调用这几个工具的功能。 这里的apt命令和APT包管理工具是完全不同的两个东西,请不要混淆了,下面我们对apt命令进行详细说明。
在前面介绍命令“apt-get install”时,已经为大家演示了如何安装软件。下面的模拟我们在使用Linux时经常会遇到的情况。现在我们执行下面的命令:
vim
终端会告诉你,找不到这个vim命令,并告诉你可以用它说明里提供命令来安装软件,如下图所示。Linux的终端往往会输出一些有利于我们解决问题的信息。 这类似Windows偶尔弹出一个对话框来告诉用户解决方法。因此,在今后的学习中,遇到问题,应该多关注终端的输出信息,说不定里面暗含着解决之道。
不知道有没有细心的读者发现,此处Linux给出的解决方案是“apt install vim”而不是“apt-get install vim”。 实际上,在Ubuntu 16.04中就引入了 apt 命令,并且越来越多Linux发行版也开始鼓励用户使用apt而不是apt-get。 前面我们提到,apt-cache、apt-config 等命令包含众多了功能,但对于 Linux 用户来说可能永远都不会使用到。 apt 命令出现就是为了解决上述的问题,它包括了 apt-get 命令使用最广泛的功能选项, 还包含了 apt-cache 和 apt-config 等命令中很少用到的功能,也就是说apt是集apt-get、apt-cache 和 apt-config 各工具之所长的工具。 不仅如此,使用 apt 命令安装或删除程序时,会有进度条显示当前的进度。
表 apt命令
命令 | 作用 |
---|---|
apt install 软件包名 | 安装指定的软件包 |
apt remove 软件包名 | 卸载指定的软件包 |
apt update | 更新软件源列表 |
apt search 软件包名 | 根据关键字搜索对应的软件包 |
apt show 软件包名 | 显示软件包的相关信息 |
apt list | 根据名称列出所有的软件包 |
上表中列出了部分常用的apt命令,可以看到apt命令比APT包管理工具更加精简, 更能满足用户的需求。用通俗一点的话讲,就是别人需要三个工具才能搞定的事情, 我只需要一个apt命令,如原来的apt-get install 命令改成apt install同样也可以完成软件的安装。
我们输入命令:
sudo apt install vim
之后,会提示你输入密码,接着便开始下载,安装软件了。软件安装完成之后,再执行命令Vim, 终端就不会再报错了,这时候就可以使用我们的Vim编辑软件,软件界面如 下图所示。
对于没有用过Vim的用户,如果你在Vim上尝试折腾一翻后, 可能会出现各种情况, 如进入到了Vim的编辑模式,输入了些内容,但不知道如何保存或退出,这些我们将在 《使用gedit、VS Code以及Vim编辑器》 章节中介绍, 现在我们直接点击终端右上角的关闭按钮或“Ctrl”+“z”强制退出即可。
使用apt-get install安装软件时,可注意到它是从Ubuntu官方源地址下载的,但Ubuntu默认官方的软件仓库都设置在国外, 这种情况下经常出现安装更新缓慢甚至下载超时等异常。实际上,国内有许多第三方软件仓库镜像源,可以从这些国内仓库安装软件工具,加快下载速度。
常用的国内镜像源有:
这些镜像站通常包含非常丰富的软件,以清华大学镜像源的网站为例,见下图,在其镜像列表中可以找到ubuntu的软件源, 点击ubuntu右侧的“?”,还可以查看到如下的帮助说明。
这四个目录中的软件都是按照软件名称的首字母进行分类,极大地方便了我们搜索某个软件,如下所示。 不过,当我们使用时,是直接通过apt工具下载的,而不需要自己来到开源镜像站中查找。
在Ubuntu下可直接在“软件和更新”的配置中修改软件源,见下图。
在弹出的界面选择“其他站点”->“mirrors.tuna.tsinghua.edu.cn”(清华大学镜像源)或“mirrors.aliyun.com”(阿里云镜像源)网址,如下图所示。
在后面我们的开发板会提供Debian及Ubuntu的镜像,但在开发板中修改软件源并没有上述的图形界面这么方便, 我们通常是使用终端去修改软件源配置文件实现的,而且在后期搭建开发环境的时候,也常常需要修改各种配置文件。 本例子在PC上进行修改,如果改得不对,还可以通过上面的图形界面修改回来,所以我们就趁这个机会先熟悉一下修改配置文件的过程吧。 修改配置文件的步骤为:熟悉配置文件的格式->修改配置文件->更新配置。
我们先来了解软件源配置文件的格式,在Ubunut下,软件源的配置是记录在文件/etc/apt/sources.list中的, 我们可以通过cat命令输出该文件的内容,查看自己电脑上的源配置:
cat /etc/apt/sources.list
/etc/apt/sources.list文件具有一定的格式如下所示。
官方软件源(/etc/apt/sources.list节选)
deb http://cn.archive.ubuntu.com/ubuntu/ bionic main restricted
deb-src http://cn.archive.ubuntu.com/ubuntu/ bionic main restricted
第三方镜像源(以清华大学镜像源为例)
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
我们以清华大学提供的镜像源为例,讲解一下Ubuntu软件源的格式。
/etc/apt/sources.list中每一行都代表了一个软件源,每行的软件源描述又可以分为四个部分,见下表。
表 软件源格式
软件包格式 | 镜像源地址 | Ubuntu发行版版本代号 | 要下载软件包的类型 |
---|---|---|---|
deb/deb-src | https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ | bionic | main restricted universe multiverse |
这四部分的说明如下:
表 Ubuntu发行版版本代号
版本 | 版本代号 |
---|---|
12.04 | Precise Pangolin |
14.04 | Trusty Tahr |
16.04 | Xenial Xerus |
18.04 | Bionic Beaver |
上表只列出了Ubuntu的LTS版本。LTS,是长期支持(Long Term Support)的缩写。Ubuntu桌面版通常每两年发布一个新的LTS版本, 本书使用的Ubuntu18.04,对应的版本代号为Bionic Beaver。
下面我们尝试通过修改/etc/apt/sources.list文件修改软件源。
建议在修改软件源前,使用如下复制命令对原文件进行备份:
# 复制一份sources.list文件的内容,以sources_bk.list的名字进行备份。
cp /etc/apt/sources.list /etc/apt/sources_bk.list
若修改后使用有问题,使用备份的/etc/apt/sources_bk.list覆盖原文件后更新即可。
由于修改/etc/apt/sources.list配置文件通常需要管理员权限, 普通用户在图形界面直接双击打开该文件时,Ubuntu系统自带的编辑器gedit只有只读权限,无法修改。 可以在终端中使用sudo以管理员的身份运行gedit,并打开/etc/apt/sources.list文件进行修改,命令如下:
sudo gedit /etc/apt/sources.list
在后面的系统应用中,我们常常需要修改某些系统配置文件,都可以通过这种方式使用gedit进行修改, 把命令中的文件名改成目标文件即可。
如果系统没有gedit或者没有图形界面,一般直接在终端下使用Vi/Vim编辑器进行修改, 不会使用Vi/Vim的话,请在学习《使用Vim编辑器》的章节后再进行修改。
把前面镜像源使用帮助的sources.list文件内容复制替换文件/etc/apt/sources.list的原内容,保存后退出即可。
用户一旦修改了软件源配置文件/etc/apt/sources.list,需要运行apt-get update命令来更新软件源中的所有软件列表。
sudo apt-get update
apt-get update命令会扫描每一个软件源地址,并为该软件源地址所具有软件包资源建立索引文件,存放在本地的/var/lib/apt/lists/目录下。
我们从上图中可以看到我们上面添加的中国科技大学的镜像源地址,在sources.list文件中选择只下载main类型的软件, 因此在apt-get update的过程中,也只会去获取main类型的软件包。此外,图中的amd64是一种64位的电脑处理器架构, 又称“x86-64”或“x64”;i386则是作为对Intel(英特尔)32位微处理器的统称。
本书的虚拟机使用的64位机器,我们打开上图选中的文件,该文件主要记录了所有适用于am64架构处理器的软件包。
上图中记录了gcc-7软件包的相关信息:
我们在开发时使用Ubuntu桌面版,它有各种图形编辑器,如系统自带的gedit或跨平台的VS Code,这些图形编辑器对用户非常友好,易于使用。 尤其是VS Code,它是我们推荐的在开发时使用的工具。另外还有一些大神喜欢用的Vi/Vim编辑器,它对新手来说实在不算友好,但是在一些场合根本没得选, 因为在使用Linux时很多时候并没有图形界面,此时只能通过终端使用命令行来控制,而在终端下Vi/Vim的编辑功能非常强大, 当在终端下需要对系统的一些配置文件进行修改时,使用Vi/Vim非常方便。
我们不建议Linux新手刚开始就拼命折腾Vim编辑器,并不是说它不好,只是希望大家聚焦于Linux开发学习本身,不要让它成为劝退大家学习Linux的拦路虎。
gedit是在Ubuntu系统下的地位就如同Windows系统下的记事本软件,它的功能不算强大,但因为是系统自带的, 说不上什么时候我们就会图方便使用它用来轻度编辑和记录一些内容。
在图形界面下使用gedit编辑器在前面已经介绍过,此处我们演示下在终端打开该编辑器。 在前面的 《使用Linux命令行/命令究竟是什么》 中提到, 命令的本质就是一些应用程序,Ubuntu系统自带的gedit编辑器,我们也可以通过终端来打开:
# 在终端中执行行下列命令:
gedit 要打开或新建的文件名
为什么要用终端打开gedit?因为在修改系统配置文件时,通常需要管理员权限,而在图形界面下通过gedit打开文件, 只能使用当前用户的身份,这种情况下是无法对这些文件进行修改的。但是,如果我们在终端下,使用sudo命令为gedit增加权限来打开这些文件, 则可以对它进行修改,在 《apt及yum包管理工具/修改软件源(命令行)》 小节就介绍了这样的方式对/etc/apt/sources.list 文件进行了修改。
执行以下命令可进行对比,使用普通用户权限与sudo权限打开配置文件的差异如下图所示。
#在后面的说明中,#号表示注释,它后面的内容不要输入到终端中
gedit /etc/apt/sources.list #以普通用户身份打开配置文件
sudo gedit /etc/apt/sources.list #使用sudo增加权限打开配置文件
Linux新手在配置开发环境时,对Linux本来就不熟悉,刚学习配置开发环境时一般又一头雾水, 再加上网上的教程一般是使用Vim来修改配置文件,新手照着敲命令使用Vim编辑器来改内容, 经过Vim的一番操作后,直接就劝退了,我们从此损失了一位未来的技术大牛。
在网上以及我们后面的各种修改配置文件的命令中,默认都是使用Vi/Vim来修改,因为系统一般自带Vi, 而且不需要区分系统是否需要使用图形界面。但是对于刚学习Linux的用户,能不用Vim就不去用,在使用带图形界面的Ubuntu时, 看到命令中的vim时心里就默认把命令中的“vim”替换成“gedit”即可。
例如:
#使用sudo权限通过vim打开文件
sudo vim /etc/apt/sources.list
#使用sudo权限通过gedit打开文件
sudo gedit /etc/apt/sources.list
以上命令区别仅为“vim”和“gedit”,即使是Vim编辑器同样也是需要sudo权限才能对文件进行编辑的, 如果不使用sudo,以普通用户的身份使用Vim编辑器打开配置文件,同样也是只有“只读”权限。所以,千万不要把Vi/Vim编辑器神圣化了。
VS Code是微软制作的开源编辑器,跨Windows、Linux及iOS平台都有一致的易用体验,推出后广受程序员们的欢迎, 配合各种插件可以打造丰富的功能,支持各种文件格式的语法高亮,甚至可以远程编辑服务器或开发板上的文件, 本书中的例子基本上都是使用VS Code编辑器写的。
在Ubuntu自带的软件中心可以找到VS Code软件,通过搜索“vscode”即可安装,但目前Ubunut采用Snap软件市场来安装软件, 暂时还没有国内的镜像下载源,所以下载可能需要花比较长的时间。
我们推荐直接在Ubuntu下使用浏览器在VS Code官网下载deb包进行安装,顺便学习deb包的安装方法。
VS Code官网地址:https://code.visualstudio.com
VS Code 的安装步骤如下:
到官网找到下载的选项,可看到Linux平台下分deb和rpm安装包,Debian和Ubuntu系统都是用deb包,如下图所示。
下载后可以在浏览器中打开下载目录,默认的目录一般为用户家目录下的“/home/下载”。
找到下载好的deb包,直接双击即可安装。
如果想体验命令行安装deb包,可以使用以下命令:
sudo dpkg -i 安装包的名字
使用命令行安装过程如下图所示。
安装完成后,可以通过“显示应用程序”中打开,如下图所示。
也可以通过终端打开,在终端下VS Code的打开命令为“code”:
# 在终端中执行行下列命令:
code
输入命令回车后稍等一会即可。
类似地,如果希望用VS Code修改配置文件,使用sudo命令增加权限即可:
sudo code 文件名 --user-data-dir
其中的“–user-data-dir”参数是VS Code提示要输入的,如下图所示。
VS Code的强大之处在于它的插件,刚开始的时候我们安装中文支持和c/c++插件即可。
点击VS Code界面左侧的“插件图标”,在输入框中输入“chinese”后搜索,可以找到插件“Language pack extension for Chinese (Simplified)”, 点击插件下的install按钮即可安装。
安装插件后一般需要重启VS Code才能生效,平时界面的右下角通常也会有各种提示,如下图所示。
VS Code本身就支持C/C++的语法高亮,但并不支持编译、运行、调试等功能,通过安装“C/C++”插件可扩展相应的功能。 在插件安装栏中输入“c”即可搜索到“C/C++”插件,直接安装,如下图所示。
前面已多次提到Vi/Vim编辑器,大部分Linux系统中都会自带Vi编辑器已方便用户在终端上编辑文件,而Vim是Vi的升级版本, 它在Vi的基础上改进和增加了很多特性,是一个功能更强大、高度可定制的文本编辑器。 如支持代码折叠、插件、多国语言支持、垂直分割视窗、拼字检查、上下文相关补完,标签页编辑等功能。 热爱Vim编辑器的用户,能把它玩出花来,甚至直接把它打造成IDE。
在对Linux服务器进行运维或控制嵌入式开发板的时候,绝大部分情况下我们只能使用终端,而在终端编辑文件时使用Vi/Vim编辑器几乎是最好的选择, 所以即使它上手不易,但我们也绝不能逃避学习。对新手来说,要求能熟练使用Vi/Vim编辑器对文件进行基本的读写修改。
在Ubuntu下,使用apt可安装Vim编辑器,执行如下命令安装:
sudo apt install vim
安装后使用vi或vim命令都可以打开,它们的基础使用方法是一样的:
vi #若系统安装了vim,该命令会自动打开vim软件
vim #打开vim软件
也可以使用如下命令创建或打开文件:
vi 文件名 #若文件存在则打开,文件不存在则创建
vim 文件名
由于Vim是在终端下使用,没有图形界面的,所以对它的所有控制都只能通过命令来实现,包括退出。对于新手来说如何退出Vim都是个问题。
最简单粗暴的Vim退出方式是使用“Ctrl”+“z”直接强制退出。
此处我们通过Vim的命令行模式退出Vim的步骤来体验它的“一般模式”和“命令行模式”。
打开Vim后,请按如下步骤进行操作,注意若开启了输入法,要先把输入法设置成英文:
执行时终端显示的内容如下图所示。
初次使用Vim时,想要在编辑器输入内容也并非易事, Vim打开后默认是在“一般模式”的, 键盘的输入都会被当成一般命令而不是文本的内容,即在该模式下的所有输入就如同在其它常用编辑器中按了快捷键。 运气好按了进入“插入模式”的快捷键,后续的输入才会被当成文本内容。
可通过以下步骤进入到“插入模式”输入内容并保存文件:
经过以上的使用演示,我们体验到了Vim编辑器的三种工作模式:
我们在使用Vim时,常常会在这三种模式之间进行切换,切换方式可以参考下图。
上图的意义就是:
Vim提供多个快捷键来从一般模式进入插入模式,见下表。进入插入模式之后,就可以正常地编辑文本了, 使用方向键来移动光标,回车键进行换行,操作方式与Windows记事本没有什么区别。
表 进入/退出插入模式的快捷键
快捷键 | 功能描述 |
---|---|
i | 在当前光标所在位置插入文本 |
a | 在当前光标所在位置的下一个字符插入文本 |
o | 在光标所在位置后插入新行 |
r | 替换当前光标所在位置的字符 |
R | 可以替换当前光标所在位置之后的字符,按下“Esc”则退出 |
ESC | 退出插入模式 |
在任意模式下按按键“Esc”可进入到一般模式。下表列出了一般模式下常用的快捷键。在一般模式下,可以进行复制,粘贴,删除,查找替换某个关键字等。
表 一般模式快捷键
快捷键 | 功能描述 | |
---|---|---|
光标移动 | k / ↑ | 光标向上移动 |
j / ↓ | 光标向下移动 | |
h / ← | 光标向左移动 | |
l / → | 光标向右移动 | |
PageUp | 向上翻页 | |
PageDown | 向下翻页 | |
nG | 跳转到第n行 | |
文本查找与替换 | /word | 在文件中搜索关键字word |
n | 查找下一个关键字 | |
N | 查找上一个关键字 | |
:1,$s/word1/word2/gc | 将文本中的所有关键字word1用word2进行替换,需要用户进行确认。(使用:1,$s/word1/word2/g则直接全部替换)。这实际是运行在命令模式。 | |
撤销重做 | u | 撤销上一步的操作,等价于Windows的Ctrl+Z |
Ctrl+r | 重做上一步的操作。 | |
删除、剪切、复制、粘贴 | d | 删除光标所选的内容 |
dd | 删除当前行 | |
ndd | 删除光标后n行 | |
x | 剪切光标选中的字符 | |
y | 复制光标所选的内容 | |
yy | 复制当前行 | |
nyy | 复制当前行后n行 | |
p | 将复制的数据粘贴在当前行的下一行 | |
P | 将复制的数据粘贴在当前行的上一行 | |
区块操作 | v | 选择多个字符 |
V | 可以选择多行 | |
ctrl+v | 可以选择多列 |
在一般命令模式下,按下键盘的冒号键“:”,就可以进入命令行模式,继续输入要执行的命令按回车即可执行。
表 命令行模式快捷键
快捷键 | 功能描述 |
---|---|
w | 保存文档 |
w | 另存为以为文件名的文档 |
r | 读取文件名为filename的文档 |
q | 直接退出软件,前提是文档未做任何修改 |
q! | 不保存修改,直接退出软件 |
wq | 保存文档,并退出软件。 |
set nu | 在行首加入行号 |
set nonu | 不显示行号 |
set hlsearch | 搜索结果高亮显示 |
! command | 回到终端窗口,执行command命令,按回车键可切回vim。 |
到此为止,Vim的基本操作就介绍完了,最后我们尝试用Vim编写一个输出hello world的脚本,熟悉Vim的操作。
在终端中执行行下列命令:
vim hello_world.sh
然后进入插入模式(在一般模式下按“i”键),输入下列代码后,保存文件并退出(退出插入模式,进入命令行模式后,输入wq并回车), 注意以下内容全为英文符号。
echo "helloworld,this is a script test!"
此脚本文件中的echo命令的作用是将其后面的文本内容直接输出到终端上。
Vim退出后回到终端,通过source命令运行刚刚编写的脚本文件:
source hello_world.sh
可以看到终端会输出“helloworld,this is a script test!”字样。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。