Skip to content

[翻译] 简谈编译、汇编、链接和加载 – part VI

Tanslated from: http://www.tenouk.com/ModuleW.html W.10  运行时链接器和共享库的加载 使用共享库的程序启动时或这一个程序请求动态加载一个共享对象时会触发运行时链接器。因此符号的解析可以在下面两个过程中的任一个完成。 1. 加载时动态链接。程序被从磁盘上加载到内存中,其中未解析的引用被列出,加载器找到所有需要的外部符号,把所有对这些符号的引用更改为相对于程序基地址的内存地址。 2. 运行时动态链接。程序被从磁盘上加载到内存中,其中未解析的引用被原样保留。第一次对这些符号的访问是无效的,从而引发一个software trap。运行时动态链接器侦测到此次trap的原因并找到所需的外部符号。然后这个被访问的符号被加载到内存并被链接到程序中。 运行时链接器包含在C的运行时库中,它加载共享库(.so文件)时会完成几个任务。动态section提供信息给链接器,告诉它这个库文件链接的其它库文件。它同时提供需要哪些重定位(reloaction)操作以及需要解析的外部符号。运行时链接器会首先加载需要的其它库文件。然后为每个库文件执行重定位操作。有些重定位仅限于库文件本身,而有些则需要运行时链接器解析一个全局符号。对于后一种情况,运行时链接器会搜索一个库文件列表来寻找这个符号。在ELF文件中,会使用hash table来进行符号的查找,所以这个过程是很快的。一旦所有的重定位操作执行完毕,就开始调用在共享库文件的init部分中注册的初始化函数。一些C++的实现使用这个特性来调用全局contructor。   W.11  符号名称解析 当运行时链接器加载了共享库文件,还需要解析库文件中的符号。这里,符号解析的顺序和范围是很重要的。如果一个共享库调用的函数碰巧在几个库文件中都存在,那么搜索这个函数的顺序就至关重要了。这也是为什么操作系统为库文件加载定义了几个选项。所有具有全局范围的对象(可执行文件和库文件)会被保存到一个列表中(全局列表)。默认,任何全局对象的所有符号对加载进来的共享库都是可用的。全局列表开始时包含可执行文件以及程序启动时加载的库文件。   W.12 动态地址翻译 以内存管理的角度看,现代的具有多任务的操作系统通常会实现动态重定位,而非静态。所有程序在地址空间中的布局几乎是相同的。这个动态重定位(以处理器的角度,称为动态地址翻译)产生一下的假象: 1. 每个进程都可以使用以0开始的内存地址,即使其它进程已经在运行了,或者同一个程序被启动多次 2. 地址空间是受保护的 3. 甚至可以让进程认为它拥有比实际物理内存大得多的内存可用(虚拟内存) 动态重定位中,每次引用地址都会动态变化。虚拟内存地址(或者称为逻辑地址)由某个进程产生,而物理地址则是运行时在物理内存中的实际地址。地址的翻译通常由处理器内嵌的内存管理单元(MMU)完成。 虚拟地址是相对于进程而言的。每个进程都相信它的虚拟地址从0开始。进程完全不知道这个地址在物理内存中的实际地址。代码完全以虚拟地址的方式运行。 如果一个虚拟地址超出了进程的(实际)地址范围,MMU可以拒绝翻译此地址,如产生一个segmentation fault。这为所有进程提供了保护。 翻译过程中,我们还可以把进程地地址空间中的一部分在内存和磁盘间移动(称为swapping或paging),这就是为什么进程可以使用比实际物理内存还大的地址空间。 动态重定位可以以下图来表示:   More complete related information can be found…

Read more

[翻译] 简谈编译、汇编、链接和加载 – part II

Tanslated from: http://www.tenouk.com/ModuleW.html W.2  对象文件与可执行文件 源文件经历汇编后会变成对象文件(文件名通常以.o为后缀),再经过链接后,就变成了可执行文件。 对象文件与可执行文件的格式有几种。如Linux上的ELF (Executable and Linking Format) 格式以及Windows上的 COFF (Common Object-File Format). 对象文件格式 描述 a.out Unix上最初的可执行文件格式.  它包含有三个块(sections):  text, data, and bss, 分别对应程序代码, 初始化过的数据以及未初始化的数据.  此格式无法包含排错信息。它能包括的唯一排错信息是被编码为一套带有不同属性的符号的、称为stabs的东西。 COFF COFF格式 (Common Object File Format) 由Unix SVR3引入 .可包含多个块, 每个块都有一个”块头(header)”. 块的数量是有限的.  COFF标准是包含排错信息的,但是也是有限的。此格式没有文件扩展名。 ECOFF COFF的一种变体. …

Read more

缓存更新的套路

看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个 […]

Read more

subprocess: python 2.7脚本中如何运行shell命令

每次用的时候都要去读一下文档,这次总结一下,记录于此,已备后用。 其实这个主要是用subprocess这个模块。 最普通的,执行命令,但不管命令的输出: import subprocess return_code = subprocess.call(“ls”,”-ltra”], shell=True) 设置”shell=True” 是告诉python在后台生成一个shell进程,然后在此shell进程中执行相应命令。 这样可以利用到shell中的一些特性,但这样做有安全风险,只有传入的命令完全可控时才这样做。   命令的返回值保存在return_code中。输出则直接输出到屏幕(stdout)。 如果需要获取命令的输出,则用subprocess中的check_output, 而非call: output = subprocess.check_output([‘ls’, ‘-l’]) print ‘Have %d bytes in output’ % len(output) print output ## if the command fails, python throws an CalledProcessError 上面的方式中,如果命令的出错输出(如果有的话)仍然会出现在屏幕上。…

Read more

Running bash on Windows 10

微软最近宣布他们正在和Cananical(Ubuntu)合作,要把bash整合到Windows 10中。这听起来像是一个很不错的主意。平时我自己在使用Windows的时候,最不满意的就是Windows的命令行了,无论是功能还是界面。如果能够在Windows上使用bash SHELL以及一些常用的unix命令行工具,如sed/awk/grep/sort等等,那将会让工作效率大大提升,感觉也更好一些。 下面的视频是Windows channel 9上的一个的一个演示。从视频中我们可以看到,在Windows的bash shell中能使用的命令还挺多。Vi,Ruby,用gcc编译hello world C代码。演示者Russ甚至使用apt-get install git命令安装了git,并使用git clone来复制了一个github上的代码库。按主持人的说法,搬到Windows上的不止是bash shell,而是整个“user mode linux”。

Read more

case语句的fall through

当然我说的是SHELL,不是其它的编程语言。 在看<学习KSH》中看到,把’;&’字串放在case语句中,会让case语句“fall through”(暂时没想到如何翻译,看下面的脚本输出来看看fall through是怎么回事)。实际 测试了一下发现,OpenBSD (5.8)以及DragonFly BSD (4.2)中的KSH不支持这个功能。因为他们的KSH所谓的pdksh衍生版(public domain korn shell),而Ubuntu (15.04)中通过apt-get安装的ksh是原始的Korn Shell,支持’;&’的fall through功能。 BASH shell则是从4.0版以后开始支持。 脚本: A=2 case $A in 1) echo “QUICK” ;& 2) echo “BROWN” ;& 3) echo “FOX” ;& 4) echo “JUMPED” ;; esac Ubuntu: acheng@cactus:~$…

Read more

IPv6中的被请求节点组播地址

这是一个有特殊用途的组播地址,主要用于重复地址检测和获取邻居节点的链路层地址(相当于IPv4中的ARP解析)。这个组播地址的前104位是固定的,为 FF02::1:FF/104, 后24位由接口的单播地址的最后24位构成。假设某个接口的单播地址为2001:3234::1:253F,那么该接口就会自动归属于组播地址FF02::1:FF01:253F。 由于IPv6地址每16位划为一段,共8段,因此前面104位(FF02::1:FF/104)中最后的8位(也即FF)要和接口的单播地址中最后24位的前8位组合在一起形成一段。我们例子中单播地址的最后24位为01:253F(示例单播地址中倒数第二段的1其实是0001的简写),因此被请求节点组播地址为FF02::1:FF01:253F。 当此链路上其它网络接口需要给此IP发送数据时,它就会先给这个组播地址发送数据,请求它的链路层地址;而我们示例接口如果收到发往此组播地址的数据时也会进行处理和响应。同样,当某一个接口给自己配置IP地址的时候,也会使用这个组播地址来进行重复地址检测;也就是说如果这个新分配的IP地址的最后24位是01:253F,那么它也会发送数据报到这个组播地址,看看是否已经有其它接口配置了相同的IP地址,如果没有收到应答,则表示没有重复地址;如果收到应答,则会比对应答数据包的源地址来判断是否重复。

Read more

unix文件中的ctime, mtime和atime

今天需要使用find命令来查找一些文件,需要找到15天前创建的文件。究竟该用哪个参数呢,ctime,mtime还是atime? 那就再来复习一下这三个参数具体的意义吧。 不过,在谈论这三个参数之前,你得先了解inode(索引节点)的概念,不然是说不清的。inode是干嘛用的?它是用来存储文件属性的一个数据结构,比如文件的权限,所有者,大小,指向本文件的连接数等,当然也包括文件的更新时间等信息(但不包含文件名以及文件的内容)。在表现形式上,inode是一个数字,每个文件都对应一个唯一的inode。可以使用ls命令的‘-i’参数来查看文件或目录的inode: root@kali:/data/dbbak# ls -li total 0 2494398 -rw-r–r– 1 root root 0 Aug 19 20:09 test 当新建一个文件时,系统会自动分配一个inode号码。 更具体的inode信息,大家可以网上搜索一下。今天不再详细介绍。 ok,有了这些背景信息,我们可以介绍这三个参数了。 ctime ctime是文件属性更新的时间。比如更新了文件的所有人,更改了文件的读/写/执行权限等。也可以理解为,任何对inode数据结构里的信息进行的更新都会引起ctime的更新(但下面atime的测试说明这个说法需要进一步考证) mtime 文件内容更新的时间。 这个是最直观的。你打开文件,编辑了其中的内容,在你保存时,系统会更新文件的mtime属性。 要注意的是,更新mtime时,通常也会需要更新ctime;有时候更新ctime却未必需要更新mtime(比如为文件添加可执行权限)。   atime 文件最后访问时间。 每次打开一个文件时,或者使用grep/sort等命令访问文件时系统也会更新文件的atime。 那么系统更新文件的atime,意味着文件的属性发生了改变,应该同时更新ctime。但下面的测试表明不是这样的。 $ stat test File: ‘test’ Size: 332 Blocks:…

Read more
Sidebar