Hadoop的三种模式以及相应的安装细节Google上一大把,其实都基本上是一些参数的设置。 下面自己在.bashrc文件中的设置: # setting in .bashrc export HADOOP_INSTALL=/home/stephenchan/hadoop-0.20.2 export CLASSPATH=.:$HADOOP_INSTALL/hadoop-0.20.2-core.jar:$HADOOP_INSTALL/lib:$CLASSPATH export PATH=$PATH:$HADOOP_INSTALL/bin 样例的代码是来自<Hadoop : The Definitive Guide>一书,由于没有拿到天气的数据,所以自己用代码生成了一个类似的样例数据,只有年份和温度,用MapReduce来取每年的最高温度,但我省去了日期中的天,保留了年。代码在standalone模式下运行即可,官方的参考文档 : http://hadoop.apache.org/common/docs/r0.20.2/cn/。目前Hadoop只在Linux下完全支持商用运行,在Unix和Windows只支持用来开发。 生成示例数据的Python代码(生成后再手动给三个年份设置最大的temp值(如999)来观察结果的正常与否): #!/usr/bin/env python import string import random import hashlib random_chars = string.digits year_list = [1990, 2000, 2010] for idx in range(1, … Continue reading →
动态链接的基本思想是把程序按照模块拆分成各个相对独立的部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接那样把所有的程序模块都链接成一个单独的可执行文件。动态链接涉及运行时的链接及多个文件的装载,必需要有操作系统的支持,因为动态链接的情况下,进程的虚拟地址空间的分布会比静态链接情况下更为复杂,还有一些存储管理、内存共享、进程线程等机制在动态链接下也会有一些微妙的变化。在Linux系统中,ELF动态链接文件被称为“动态共享对象(DSO,Dynamic Shared Objects),简称共享对象,它们一般都是以“.so”为扩展名的一些文件,而在Windows系统中,动态链接文件被称为动态链接库(Dynamical Linking Library),即平时见到的以“.dll”为扩展名的文件。 动态链接库的特点与优势 把函数库推迟到程序运行时加载的好处有几个: 可以实现进程之间的资源共享。就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝。如果有,则让其共享那一拷贝(共享代码段,数据码各自独立一份);只有没有才链接载入。这种模式虽然会带来一些”动态链接“额外的开销,但却大大地节省了系统的内存资源,通过一定的优化,与静态链接相比,性能损失大约在5%以下。 程序升级变得简单。用户只需要升级动态链接库,而无需像静态链接那样重新编译其他原有的代码就可以完成整个程序的升级。 可以使链接载入由程序员在程序代码中控制,如dlopen、dlsym、dlclose等等。
ELF文件类型 ELF文件主要分为三种类型: 可重定位文件(Relocatable File)包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。 可执行文件(Executable File) 包含适合于执行的一个程序,此文件规定了exec() 如何创建一个程序的进程映像。 共享目标文件(Shared Object File) 包含可在两种上下文中链接的代码和数据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件。其次,动态链接器(Dynamic Linker)可能将它与某个可执行文件以及其它共享目标一起组合,创建进程映像。 ELF文件的数据表示 ELF文件头结构及相关常数被定义在”/usr/include/elf.h”里。ELF目标文件中的所有数据结构都遵从自然大小和对齐规则。如果必要,数据结构可以包含显式的补齐,例如为了确保4字节对象按4字节边界对齐。数据对齐同样适用于文件内部。下面为ELF中常用的数据格式: 名称 大小 对齐 描述 Elf32_Addr 4 4 无符号程序地址 Elf32_Half 2 2 无符号短整型 Elf32_Off 4 4 无符号偏移地址 Elf32_Sword 4 4 有符号整型 Elf32_Word 4 4 有符号整型 ELF除了32位版还有64位版本,数据类型的名称和大小也相应地变化(Elf64_Addr…)。
对于32位平台下的4G的虚拟空间,在默认情况下,Linux操作系统将进程的虚拟地址空间划分为两部分,其中操作系统本身用去了一部分:从地址0xC0000000到0xFFFFFFFF,共1GB。剩下的从0×00000000地址开始到0xBFFFFFFF共3GB的空间都是进程使用的。而对于Windows操作系统来说,它的进程虚拟地址空间划分是操作系统占用2GB。 覆盖装入(Overlay)和页映射(Paging)是两种很类型的动态装载方法,它们所采用的思想都差不多,原则上都是利用了程序的局部性原理。动态装入的思想是程序用到哪个模块,就将哪个模块装入内存,如果不用就暂时不装入,存放在磁盘中。 覆盖载入在没有发明虚拟存储之前使用比较广泛,现在已经几乎被淘汰了。覆盖载入的方法是把挖掘内存潜力的任务交给了程序员,即是程序员在编写代码的同时要自己手动对程序模块进行内存和磁盘的切换,使不需要的代码切换出磁盘,腾出空间给需要执行的代码块。 与覆盖载入的原理相似,页映射也不是一下子就把程序的所有数据和指令都载入内存,而是将内存和所有磁盘中的数据和指令按照“页(Page)”为单位划分分成若干个页,以后所有的装载和操作的单位就是页。以目前的情况,硬件规定的页大小有4096字节、8192字节、2MB、4MB等。其实这个是属于操作系统存储管理的一部分,内存页的切换会使用先进先出、最少使用等等算法。 可执行文件的装载 可执行文件的装载和进程的建立大概经历3个步骤: 首先是创建虚拟地址空间。一个虚拟空间是由一组页映射函数将虚拟空间的各个页映射至相应的物理空间,那么创建一个虚拟空间实际上并不是创建空间而是创建映射函数所需要的相应的数据结构。在i386的Linux下,创建虚拟地址空间实际上只是分配一个页目录(Page Directory)就可以了,甚至不设置页映射关系,这些映射关系等到后面程序发生页错误的时候再进行设置。 读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系。上面一步的页映射关系函数是虚拟空间到物理内存的映射关系,这一步所做的是虚拟空间与可执行文件的映射关系。当程序执行发生页错误时,操作系统将从物理内存中分配一个物理页,然后将该“缺页”从磁盘中读取到内存中,再设置缺页的虚拟页和物理页的映射关系,这样程序才得以正常运行。当操作系统捕获到缺页错误时,它应知道程序当前所需要的页在可执行文件中的哪个位置。 将CPU指令寄存器设置成可执行文件入口,启动运行。这一步涉及了内核堆栈和用户堆栈的切换、CPU运行权限的切换等等。跳转到入口指令其实就是在ELF文件头中e_entry记录的可执行文件入口地址。
url映射是目前流行的框架都提供的基本功能,参考了django的url映射的源码,用python实现url映射的主要逻辑还是比较简单的。主要是由两个部分组成: 将处理函数的命名空间解析成模块,使用__import__,导入模块,获取处理函数的引用(见get_callable()); 匹配访问路径,提取参数,使用正则表达式进行匹配。 # add url_base as namespace to handlers in url_patterns def include(url_base, url_patterns): for index, src_pattern in enumerate(url_patterns): pattern = list(src_pattern) pattern[1] = “%s.%s” % (url_base, pattern[1]) url_patterns[index] = tuple(pattern) return url_patterns # get module name and func … Continue reading →