裸机编程与OS环境编程的有关思考
这里的所谓的裸机编程指的是为“无OS支持的硬件系统编程”,而实际的编程工作肯定需要一个环境,通常这样的情况中,编程和编译的环境叫做“宿主机”,最终的程序在“目标机”上运行(交叉编译)。而OS环境编程指的是最终运行的程序是在有操作系统支持的环境中运行,而编程和编译的环境,可能是运行程序的机器(本地编译),也可能不是(交叉编译)。
裸机编程现在主要是正对低端的嵌入式系统,如SCM(single chip machine)、各式MCU、DSP等。当然,编写PC的bootloader肯定也属于裸机编程。
裸机编程的最原始办法是用汇编语言(一种机器指令的一一对应的记法,和加上一些简单的汇编伪指令),只能使用很有限的指令集,每行代码只能做微小的事情。因此现在裸机编程也普遍使用更高级的语言(通常是C语言),那么从C语言转换到汇编语言这个过程就叫做编译。编译器根据不同的机器,将通用的C代码转化为特定的机器代码,只有十分少量的机器代码仍然需要用到汇编,这其实是一种混合编程的模式。那么,编译器实在是一种十分重要的工具,编译的理论和实践知识也会十分丰富。
在有OS支持的环境中编程则更加便利了。首先OS管理并扩展了整个机器资源,提供了一个通用的API系统调用接口,程序员通过这个接口与硬件资源打交道,因此在OS上编程更加不需要考虑机器的特性,换句话说就是移植性最佳。作为资源的扩展,OS提供了大量的机制(包括进程、内存管理、设备操作等等)和库文件(这些库文件属于可重用的代码),让编写实用程序更加便利。
其次,编译器与OS之间的关系非常紧密,OS环境编程很少有人用汇编代码,而是可以使用各种层次和类型的高级语言。很容易看出来OS环境编程使用的编译器,其功能要比裸机编程的编译器广泛的多,尽管它们是有紧密的联系。举例而言,gcc编译器能够为多种的硬软件平台编译C/C++程序:可以用gcc编译本地程序,也可以用xxx-xxx-gcc在宿主机上交叉编译目标机器的程序;可以用gcc编译裸机程序,也可以编译OS环境下的程序。总的来说,gcc编译出来的OS环境可执行文件,是裸机环境可执行文件的“超集”。看一下下面这段最简单的makefile代码:
key_led.bin : crt0.S key_led.c arm-linux-gcc -g -c -o crt0.o crt0.S arm-linux-gcc -g -c -o key_led.o key_led.c arm-linux-ld -Ttext 0x0000000 -g crt0.o key_led.o -o key_led_elf arm-linux-objcopy -O binary -S key_led_elf key_led.bin clean: rm -f key_led.dis key_led.bin key_led_elf *.o
这段代码编写了一个ARM目标机器上用按键控制LED的程序。gcc的编译首先将其编译链接成elf格式的文件,然后用objcopy工具转换成裸机代码bin文件。因为elf的可执行文件格式是linux系统的标准支持格式,这种文件中不仅含有二进制机器码,而且(如果有需要的话)会含有大量的符号与控制信息(往往是文本格式的),这些符号与控制信息能让这个程序与OS交互,并得到OS的支持。在裸机上执行程序时,仅仅需要机器直接能识别的二进制机器码bin文件,这是一种纯净的二进制机器码文件。从这个过程可以看出来,编译器与OS的关系的确非常紧密。
===================================================================
下面考察实际的linux/UNIX系统中的程序描述(based on linux programing 4th edition)。
概略
linux应用程序表现为两种类型的文件:可执行文件和脚本文件。可执行文件能够直接运行,它们包含二进制的机器代码和一些OS必须了解的控制信息。脚本文件被解释器一句句的执行,事先并没有编译成最底层的机器码。脚本文件有很多种,如python、shell等,java虚拟机类似一种解释器,但是它解释java中间码,性能比一般的解释器好。
shell是linux的人机交互界面,本质上来说它是个解释器,解释用户输入的每条指令,当然也可以解释用户编写的脚本。linux标准的程序执行搜索路径有:
/bin : /usr/bin : /usr/local/bin : /sbin : /usr/sbin
可选的操作系统组件和第三方应用程序可能被安装在/opt目录下,用户通过PATH环境变量来添加默认搜索的目录。从shell执行的程序会继承shell的环境变量,但程序的修改不会反向影响到父程序shell。
linux中的文本编辑器可以选择vim、emacs或者更可视化的eclipse等工具。
开发环境:
1、应用程序。/bin: /usr/bi: /sbin: /usr/sbin 这几个目录一般存放最常用的系统程序,而后来添加的程序往往存放在/opt:/usr/local中,它们分离的系统原本的程序和后续添加的程序。对于个人的程序或开发程序,最好在/home目录中存放它。(usr的意思不是user啊骚年!!是Unix Software Resource !!!)
gcc的驱动程序通常存放在/usr/bin 或者/usr/local/bin中,它调用gcc编译器的其它应用程序,可能存放在/usr/local/bin中,或者其它gcc知道的位置。
至于哪些程序是系统程序,这很难界定,linux kernel本身不带有任何程序,仅仅提供一个API接口。一个最小的简化版系统程序配置如busybox包含常用的如shell及其命令等,仅仅至于数百K的体积。
2、头文件。用C语言或者其它语言进行设计时,需要头文件的目的一般是需要常量的定义,或者需要对系统函数及库函数调用的声明(这些定义和声明可以是来源于用户,也可以是来源于标准库、扩展库)。linux中C语言的头文件总是位于/usr/include,依赖特定版本的头文件通常位于/usr/include/sys或者/usr/include/linux 。
3、库文件。库,是一组预先编译好的函数的集合,这些函数按照可重用的原则编写。标准系统库文件存放于/lib和/usr/lib目录中,其它扩展库可能存放在其它lib目录中。库的名字必须是以lib开头,随后部分指明库的功能,.a代表静态库,.so代表动态库,可能有 .la文件(*注)。虽然库文件和头文件一般存放在标准位置,但可以也编译时用”-L”搜索一个特殊的位置。在程序中如果引用动态库,在编译时要说明动态库的位置,程序运行态也需要库在指定的位置存在。
对于linux来说,负责装载动态库并解析客户程序所引用的函数的程序(动态装载器)是ld.so,或者是ld-linux.so.2/ ld-lsb.so.2/ ld-lsb.so.3。程序运行中搜索动态库的额外位置,可以再文件/etc/ld.so.etc中配置。也可以用ldd程序来查看一个程序运行时需要的动态库。
*注:.la文件的详解 http://blog.flameeyes.eu/2008/04/what-about-those-la-files
总结一下就是:
1、可以隐藏具体操作系统的共享库实现的不同,比如Linux是so,Windows是dll。有了.la,统一连接.la文件就可以了
2、连接静态库的时候可以从它来获取静态库的依赖关系。动态库(ELF based .so file)里本身保存了这个信息,不需要.la来获取这个信息。
.la文件理论上是可以不要的,而且如果要实现真正的multilib支持,是一定不能要.la文件。
如果不用.la文件,连接静态库的时候理论上说可以用pkg-config –static来获得依赖关系(库)。
但是现在,不是所有的库都提供相应的.pc文件
现在有些Gentoo开发者和用户正在尝试移除系统里的.la文件,并修复随之带来的问题,以求为就将来portage完美的multilib支持打下坚持的现实基础。
- 附
有关这方面的详细内容可以参考:
《深入理解Linux内核 · 第三版》第20章 程序的执行
《Linux程序设计 · 第四版》第4章 linux环境
有关OS环境编程的标准化内容可以参考:
《Linux程序设计 · 第四版》第18章 linux标准
《UNIX环境高级编程 · 第二版》第2章 UNIX标准化及实现
from:http://www.cnblogs.com/andrew-wang/archive/2012/12/13/2816897.html
裸机编程与OS环境编程的有关思考的更多相关文章
- Atitit.可视化编程jbpm6 的环境and 使用总结...
Atitit.可视化编程jbpm6 的环境and 使用总结... 1. Jbpm的意义 1 2. Jbpm6环境配置 2 2.1. Down 2 2.2. Install eclipse jbpm p ...
- UNIX高级环境编程1
UNIX高级环境编程1 故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表 ...
- Linux环境编程相关的文章
Linux环境编程相关的文章 好几年没有接触Linux环境下编程了,好多东西都有点生疏了.趁着现在有空打算把相关的一些技能重拾一下,顺手写一些相关的文章加深印象. 因为不是写书,也受到许多外部因素限制 ...
- Unix环境编程基础下
Unix出错处理 当UNIX系统的函数出错时,通常会返回一个负值.我们判断函数的返回值小于0表示出错了,注意我们并不知道为什么出错.例如我们open一个文件,返回值-1表示打开失败,但是为什么打开失败 ...
- UNIX环境编程初步认识——编程环境搭建
前言 前期学习了Linux的一些基本知识后,在借助前期的学习的基础上想再初步认识一下操作系统的一些环境编程体系相关知识,当中环境的配置和搭建费了非常大的劲,须要一点点摸索和尝试,下边是环境搭建的 ...
- UNIX环境编程学习——反思认识
学习情况: 有关UNIX系统环境编程的学习时间用来非常长的时间.可是感觉效果还是不是太好,在中间经过了期末考试.用来非常长的时间用来学习专业课.就将该过程的学习放到了一边上,放假以后又回家造成了 ...
- UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数
UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数 gethostname() getppername() getsockname() gethostbyname() ...
- python——os平台编程
一.os平台编程需求 1.目录文件的操作 对系统目录,文件的操作方法 2.程序的定时执行 3.可执行程序的转换 python程序向可执行程序的转换 二.目录文件操作 root:当前目录: dirs:当 ...
- Linux 环境编程:dirfd参数 有关解析
背景 在Unix环境编程中,系统提供了很多以at结尾的函数,如openat.fstatat等,而这类函数通常有一个特点,就是形参列表中多了int dirfd 例如: int open(const ch ...
随机推荐
- Python实战:Python爬虫学习教程,获取电影排行榜
Python应用现在如火如荼,应用范围很广.因其效率高开发迅速的优势,快速进入编程语言排行榜前几名.本系列文章致力于可以全面系统的介绍Python语言开发知识和相关知识总结.希望大家能够快速入门并学习 ...
- ASP.NET 资料下载
public void downloadfile(string s_fileName) { HttpContext.Current.Response.ContentType = "appli ...
- 高效删除 ListItem
The most efficient way to a lot of transaction in SharePoint is using of SPWeb.ProcessBatchData meth ...
- css3新增加的选择器
css3新增加的选择器 一.属性选择器: E[attr] 只要有属性名E[attr=value] 属性名=属性值E[attr~=blue] 包含这个blue整个单词就可以E[attr^=c] 以这个字 ...
- 排序算法(冒泡,选择,快速)Java 实现
冒泡 排序: public static void Bubblesort(int [] a) { for(int x=0;x<=a.length-1;x++) { for(int y=0;y&l ...
- .NET下的加密解密大全(2):对称加密
本博文列出了.NET下常用的对称加密算法,并将它们制作成小DEMO,希望能对大家有所帮助. 公共代码[csharp]static byte[] CreateKey(int num) { byt ...
- 深入了解shell
接触linux很久了,但一直没有总线,老是尝鲜,什么都想学,但好多没多没有记住,特的总结了一些基本的东西,查了很多资料,不完善的方面我会慢慢的更新…… 操作系统与外部最主要的接口就叫做shell. ...
- 【html】【2】html引入外部文件js css
1>引入js 我们只是写了简单必须的html标签,从未给标签添加点击事件,这次页面添加事件. >写入html页面,可以在<head>标签内 也可以在<body>标 ...
- ZOJ 1057 Undercut(简单模拟)
Undercut 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=57 题目大意:a card game,two pla ...
- .NET开源工程推荐(Accord,AForge,Emgu CV)
本人用C#开发了一些项目,下面的开源工程给了我很大的帮助——详细的源代码介绍加丰富的实例运用,是非常不错的学习资源,分享给大家,同时附上我的相关开发项目. Accord.NET The ...