宇宙最强调试器DDD(Data Display Debugger)

Linux主流调试器是gdb,但它是纯命令行界面的,调试起来不方便,我需要更强大的力量。在试用了各种工具之后,我相信我找到了,是的没错,就是它——宇宙最强调试器——DDD。 DDD介绍 DDD全称Data Display Debugger,当我第一次见到它时,它的界面着实让我吃了一惊,如此的简陋,如此的怪异,我甚至想立刻删了它,但是当我见识到它强大的功能时,我被深深的震撼了,如此的飘逸,如此的不羁,我的脑海中突然想到了一个词来形容它——犀利! 没错,就是这么犀利,它是gdb的最优图形化前端,它继承了gdb的所有功能,它还加入了数据结构可视化能力,什么一维二维栈数组,二叉三叉N叉树,DDD统统都能用图形显示出来。 小伙子,你还在为调试犯愁么,你还在为红黑树写了半天就是不对而沮丧么,如果你真的遇到了这样的问题,那么我想DDD一定适合你。 它含蓄深沉,它隽永内敛,它在百度上搜不到多少资料,它就是这么低调,这么孤寂,它等待着你去发现,去使用,去震撼这个世界,去拿起它的锋芒——傲视群雄! DDD安装 嗯,…

使用bochs运行Linux Kernel-2.4.0

上一篇博文讲了如何制作bochs硬盘镜像并且将grub装进去,这样我们可以在启动bochs后进入到grub界面。 这篇博文我们将2.4内核写入硬盘镜像,这就可以使用bochs直接启动内核了。 我的实验系统是这么部署的:CentOS 6.4 VMware虚拟机上修改代码和配置文件,用git做版本管理,同时还开着另一台虚拟机RedHat Linux 7.3,专门用来编译内核代码,毕竟2.4内核很老了,编译环境不能使用现代Linux系统,必须使用2001年左右的系统。每次在CentOS上修改完代码或配置就在RedHat上用rsync将数据同步下来,进行编译、安装、测试,这样最方便。用于开发的系统不必反复重启,用于编译的系统就是实验平台。 编译内核*(这一步在RedHat上进行)* 这一步在这里就不展开讲了,我对内核做了精简,不必要的选项全部关闭了,大大缩短了编译时间。其中, Block devices ---> RAM disk support 这个选项也被我关闭了,那内核启动的时候自然就不需要Initial RAM disk (initrd)了,所以待会儿更改grub.conf的时候不用配置下面这一行了。 initrd…

使用bochs和grub建立可引导硬盘镜像

bochs,发音同box,是我非常喜欢的虚拟机,灵活易用方便配置,功能极强,用来调试Linux内核是非常合适的。这篇博文主要讲解如何建立硬盘镜像,并且将grub安装上去,最后的结果就是bochs启动后能进入到grub引导界面。下一篇博客再讲解如何在镜像上安装Linux内核。 实验环境: CentOS 6.4 x86 硬盘基础知识 硬盘的专业术语中有:柱面,磁头,扇区,每磁道扇区数这几个概念。 每个盘片有两个磁头(Head),分别位于两面上,从0开始依次编号,一般来说硬盘有8个盘片,共计16个磁头,编号0-15。 每个盘面都有很多同心圆轨道称为磁道(Tracks),所有盘面上半径相同的磁道正好堆叠成一个圆柱面,称为柱面(Cylinders),它和磁道编号相同,都是自外向内从0开始编号。 每个磁道上划分出很多弧段,称为扇区(Sectors),每个磁道上的扇区都从1开始编号,每个扇区512字节,一个磁道一般有63个扇区,编号1-63。 磁盘定位可以使用CHS方法,即柱面、磁头、扇区。比如MBR的CHS=0/0/1,…

Kernel 2.4.0 之 head.S 为何用两次 jmp 刷新 EIP 寄存器

在arch\i386\kernel\head.S文件中,自line 100开始有这么几行: movl %cr0,%eax orl $0x80000000,%eax movl %eax,%cr0 /* ..and set paging (PG) bit */ jmp 1f /* flush the prefetch-queue */ 1: movl $1f,%eax jmp *%eax /* make sure eip is relocated */ 1: /* Set up the stack pointer */ lss stack_start,%esp 我看了很久都不明白第一次跳转到底是为了什么,情景分析那本书上说这是为了刷新指令预取队列,我把Intel手册翻了个遍也没找到关于预取队列的详细信息,…

Linux 2.6、4.3内核编译过程的感受与总结

之前编译过2.4.10版本的内核,很好编译,中间曾经漏下了SCSI low-level drivers下的BusLogic SCSI support选项导致没法启动系统,后来打开该选项后就行了,随手关闭一些没用的选项后编译速度非常快,30秒之内完成编译。当初以为内核编译也不过如此,直到这四天开始编译更新的内核才让我吃了大亏。 我起初的想法是编译一个极其简洁的内核,去掉网络、USB、光驱、等等所有没必要的东西,只留下核心功能,越精简越好,于是在1月21号我就下载了linux-2.6.34.tar.gz源码包,然后开始make menuconfig配置内核,当时只想着精简功能以便缩短编译时间,只关注有没有编译错误,期间由于gcc 3.4兼容版和binutils 2.20版本不匹配导致了链接失败,后来更新了gcc到4.4.7版本就好了。整个过程我都在关注编译时间是否缩短,忙活了一天,效果明显。一路精简下去,把便宜时间缩减到了2-3分钟左右,当时很高兴,觉得要成功了。 结果到了1月22号我开始引导系统时发现根本没法启动,解决一个错误又出一个错误,都是关闭了不该关闭的选项造成的,最终也没启动成功。我知道是有些重要选项被我关了,…

Ghost 博客系统终极安装教程,装不上来打我!

先放出Ghost博客项目地址:https://github.com/tryghost/Ghost 前言 Ghost这个博客系统可真是难装,第一次装失败后放弃了一段时间,转而用的JustWriting,但是这个系统也太精简了......之后我决定回归ghost!我在一个国外哥们儿的博客上找到了一篇Ghost安装参考教程,结合官网文档略加修改成功安装。后来经历了好几次重装和升级,我现在对Ghost的安装和配置已经轻车熟路。顺便吐槽一下,官方文档写的有点混乱,各种链接跳来跳去,完全不按流程来,我第一次安装愣是没看懂。那里面还要求用浏览器打开本地2368端口进行预览,我VPS连个图形界面都没有,预览个啥。 好了,废话不多说,正文开始,本文对官网教程做了整编,让你轻松拥有自己的博客。 Ghost+Web服务器转发原理介绍 官方文档建议使用Nginx作为Ghost的前端来转发80端口请求,那么Ghost的工作总流程就可以描述为: Nginx监听80端口,Ghost一直监听本地127.0.0.1:2368端口,你从外网访问www.xxx.com时,Nginx从80端口接收请求,将之转发到本地127.0.0.1:2368端口,然后Ghost就收到访问请求了。 可是为什么不直接让Ghost使用80端口呢却要依赖Web服务器转发呢?…

Linux 0.12内核与现代内核在内存管理上的区别

0.12内核的内存管理比较简单粗暴,内核只用了一个页目录,只能映射4G的线性空间,所以每个进程的虚拟空间(逻辑空间)只能给到64M,最多64个进程;每个进程都有对应的任务号nr,当一个进程需要分配进程空间时,只需要nr乘以64M就可以得出该进程空间的线性起始地址。然后该进程的代码段、数据段描述符里面的基址字段会被设定为(nr x 64M),同时可以为进程分配页目录项和页目录表用以承载映射关系。 之后如果进程要访问自己空间内的某个地址时就会首先用基地址与程序内32位偏移地址(逻辑地址)合成出线性地址,这个合成出来的线性地址一定在(段基址)~(段基址+段限长)之间,也就是(nr x 64M ~ nr x 64M+64M)之间。然后用这个线性地址遵循:“页目录项-页表-页表表项”这样的顺序找到对应的页表表项,也就找到了物理地址,就可以真正的存取数据了。 但是在现代内核里,内存管理有很多不同。 首先,线性地址空间不会改变,32位CPU可寻址4G线性空间。这个是唯一的。 但是每个进程都有自己各自独立的4G虚拟空间,那么这是如何做到的呢?其实是每个进程给它一个自己的页目录,这样每个进程就能拥有4G的虚拟空间(逻辑空间)…

C语言extern引用AT&T汇编中的变量,任意转换类型

今天研究出了一个小问题,在C语言里引用汇编的变量,会是什么结果,汇编中的变量没有像C语言中int类型那样的类型约束,可以把数据当作任何类型处理,那么传到C语言中我们应该当作什么类型处理呢。 换句话说,在汇编里定义变量var,在C语言里引用,我们肯定要用extern声明var外部变量,那么extern后面接什么类型?是extern int var吗?还是 extern short var。 以下内容需要注意C语言和汇编语言混合编译的方法,gcc test.s main.c 这样直接调用gcc处理汇编和C语言文件就可以自动搞定了。 实例一 汇编程序:(是的,就这么短小) .global var #注意现在的汇编器不再要求被C语言引用的变量名前加下划线 .data var: .fill 10,4,9 #填充10个单元,每个单元4字节,每个单元的值为9 C语言: #include <stdio.h> extern int var;…

GCC 内联汇编约束字符 m 的用法

首先是这么一段代码(例一): #include<stdio.h> void main() { char c; //int tmp; char *s="abcdefg"; asm("movb %1,%0\n\t" :"=d"(c) :"m"(*s)); printf("out:%c\n",c); } 这段代码运行后会出现什么结果呢?很显然,是out:a ​但是"m"(*s)…

Linux下用C语言调用GAS汇编——综合实例

紧接上一篇博文,上篇写的是用GAS汇编调用C语言,这次讲用C语言调用GAS汇编。​还是同样的功能,实现两个数值的交换,把参数从C语言传递进汇编,再用C语言接收从汇编函数返回的返回值,返回值又分为普通整数返回值和字符串返回值。 ​首先建立三个文件,分别为main.c、retstr.s、swapint.s。其中main.c是C语言文件,也就是主函数所在,swapint.s是汇编函数,用于交换两个变量的数值并返回一个整数值给C语言函数,retstr.s也是汇编语言函数,用于演示汇编语言输出屏幕提示,采用了直接写入stdout和调用C库两种方式,之后返回一个字符串给C语言函数。 main.c的代码如下: #include<stdio.h> char *retstr(); #C程序默认函数返回值为整数值,这里要声明下,应该是字符串指针。 int main() { int a; int b; int c; char *str; a=10;…