广告
嵌入式Linux跟桌面Linux一样,是一个操作系统。从单片机走过来的童鞋常常习惯于直接控制寄存器,事必躬亲,从零开始实现想要的功能。而在嵌入式Linux的世界里,我们首先要抛弃这个思想,应把它作为最后没办法的办法。
如同我们想要在windows系统中编撰一个程序,首先想到的不是操作CPU芯片的寄存器,而是学习WindowsAPI一样。我们在嵌入式linux编程时linux mint,首先想到的应当是使用现成的驱动或软件或LinuxAPI。没有的话瞧瞧能不能更改一下现成的资源为己所用。还是不行的话才考虑自己从头开始写。
嵌入式Linux大楼是由好多层组成的,当我们想找一个人时,首先要明晰他在那一层楼。同样的,我们碰到问题时,首先要晓得是那个方面的问题,之后才有可能晓得到那里找寻答案。下边我们把这座大楼进行一下拆解。
我们平常使用Linux系统的话,最常用的工具就是Shell(或则用windows中常见的说法:命令行),初学者接触Linux的第一个东西常常也是shell。其实你已然晓得,把shell命令组合上去写成一个文件,亦称shell编程,也是一门学院问,它能做的事好多很强悍,但仅限于对Linux系统的操作。
我们一定不会用shell命令去编撰一个显示屏程序,或则一个GPS导航程序。并且作为嵌入式Linux开发来说,shell不可能作为最终产品工作的平台,由于我们不能要求用户在屏幕中输入代码来实现功能。为此我觉得对嵌入式开发来说嵌入式linux操作系统原理,shell命令无需考量,把握基本操作就够了。
shell基本操作主要包括:获取命令帮助,抵达指定目录,查看目录内容,权限更改,文件的复制粘贴等基本操作,文件搜索,文件内容查看和编辑,系统死机重启……(这种只是最基本的,前面再渐渐学别的命令,例如学习进程编程时,再学习进程相关的命令;学习C语言编程时,再学各类编译和调试命令也不迟)
学习嵌入式Linux,我们的最终目的是制做一套嵌入式系统来实现功能。常常须要用C/C++或Python等其他语言来编撰程序,而且编程之前我们要先明晰一些基本概念。
最基本的,当我们编撰程序时,首先要明晰嵌入式Linux分为用户空间和内核空间。用户空间是应用程序运行的空间,内核空间就是操作系统和驱动程序运行的空间。这是从软件的角度来说的,对应于ARM芯片来说,就是芯片的不同“工作模式”。这两个空间是通过“地理隔离”实现相互完全独立的,它们各自的程序使用不同的显存地址区间,各自使用自己的头文件(有些头文件在两个空间内甚至是重名的,要注意分辨)、各自调用属于自己空间的函数(哪怕实现的功能相同,例如printf()和printk()),但是不能相互直接访问(用表针也不行)。(意味着学习这两部份的编程时要学习两套独立的知识体系)
内核空间相关的东西有:Linux内核源码、内核编译和配置、内核移植、文件系统、Busybox、设备驱动程序编撰、中断编程……
用户空间相关的东西有:Shell、应用程序编译和调试、进程、线程、文件IO编程、网络通讯相关、Qt图形界面编程……
假如你仅仅要开发应用程序,那你就可以远离内核空间这些东西了。对你来说,驱动程序、底层硬件、操作系统的工作方法等都是透明的,你写的程序在别的芯片上也能跑得挺好。
但若果你想要开发驱动程序,或则订制自己的操作系统,或则你想向一片“全裸”芯片中写入操作系统,并使它正常运行上去,那就得学习内核空间的知识了。
假如你想让“全裸”芯片运行上去,就会碰到一块比内核更底层的东西,Bootloader。它是在内核启动前运行的一段程序,拿来初始化硬件、建立显存空间映射等,与芯片的品牌、型号非常相关。我们一般对一些现成的Bootloader进行更改来满足需求,常见的Bootloader有U-Boot、Vivi等。
再多说一句,假如想从零开始做一个嵌入式设备,还有更底层的问题须要解决和学习:电路设计、PCB布线等。
为此,我们看见的嵌入式Linux书籍就可以简略分成两个方向:一类讲嵌入式Linux应用程序编程,另一类讲怎么搭建一个完整的嵌入式Linux平台。分别对应的就是用户空间和内核空间的事情。
尽管用户空间和内核空间是独立的,但如同Windows提供了API,容许我们对系统进行操作一样,用户空间的程序也可以通过系统调用来访问内核(就是一些的C语言函数)。但因为系统调用特别基础,所以有时使用上去很麻烦。例如说一个简单的给变量分配显存空间的操作,就须要动用多个系统调用。Linux定义一些库函数(API)来将系统调用组合成个别常用的功能,以便捷我们编程(同样是C语言函数)。因而,我们在读他人的程序时,就要分辨其中的函数是系统调用,还是库函数,还是C/C++标准库中的函数,还是用户自己定义的函数。假如是前二者,就可以到各个地方搜索相应的资料,这样学习上去就快好多。
这么shell程序和我们用C/C++编撰的程序有哪些区别呢?事实上,我们在shell中写的每一个命令,都对应了一个程序,在程序内部就是通过调用各类API来实现相应功能的。因而用shell能实现的功能,理论上都能用C语言实现。
作为嵌入式Linux开发初学者,简单熟悉了shell之后,就可以开始进行一些C语言编程的尝试了。
我们最早接触编程通常都是在学院的编程课上,并且常常用的是VisualC++6.0。窃以为这是让我对编程原理常年困扰不解的罪魁帮凶!啥是环境变量?为何要设置include路径,lib路径?为何一点编译按键都会下来这么多后缀名不同的文件?那些很基础很重要的问题都被VC6.0这个壳体掩藏了。但哪怕你在Linux中使用gcc编译一个最简单程序linux系统下载官网,一定都会像我一样马上明白把一个.c的源文件弄成一个可执行文件,中间到底发生了哪些事情。假如你再用gdb调试一个程序,都会明白得更多一点。
关于C/C++编程的基本工具,我们须要学习的有:vim等代码编辑器、diff等文件比较的shell命令、gcc等编译器、gdb等调试工具、交叉编译等。这儿须要非常提及一个重要工具(网站):github,按照百度的解释,它是一个“分布式的版本控制系统”,初学者还用不到版本控制,那就可以单纯把它当作一个开放的源代码库。这个网站里有大量优秀的源代码供学习和使用。
学习了基本的编程方式,我们就该接触Linux的API等内容了。其实,我们的嵌入式系统要与设备进行交互,只用C/C++标准库是不够的。在此之前,须要构建一个Linux的重要概念:一切皆文件。甚至硬件设备对Linux系统来说,也是文件。这样对设备的操作就等同于对文件进行读、写,或读写以外的操作。这部份内容在各类书籍资料中一般以“文件IO编程”命名,作为一个章节来写。我认为这是应该第一个来学的东西,由于看见自己能随便操控文件和外设是一件让人很激奋的事情!成就感是继续学习的一大动力!
另外一个重要内容是嵌入式linux操作系统原理,理解进程和线程。通过学习这个部份,能管中窥豹地大致感受到Linux系统怎样进行调度,你的程序是怎样在Linux中运行的。这是操作系统原理的内容,但作为非软件专业出身的人,没办法,只能自学了。
其他应用程序编程如网路编程、Qt图形编程等就不一一说明了。
驱动程序可能是我们将来接触内核空间碰到的第一个内容。不过暂时还没哪些非常想说的。内核空间距离初学者还是有点远的……以后再来学这部份内容。