汇编之路-栈操作与栈帧
结构化程序的一个最基本的单元就是“函数”或者叫“过程”。在汇编这一层自然也相应的有支持这些概念的指令操作,如栈操作和栈帧的概念。 首先这里要为“打开汇编之门”那篇blog补充一点的是:汇编语言是与机器相关,这里的一切都是基于IA-32机器平台的。 ...
结构化程序的一个最基本的单元就是“函数”或者叫“过程”。在汇编这一层自然也相应的有支持这些概念的指令操作,如栈操作和栈帧的概念。 首先这里要为“打开汇编之门”那篇blog补充一点的是:汇编语言是与机器相关,这里的一切都是基于IA-32机器平台的。 ...
工作这么长时间,一直在C语言这一层面上钻研和打拼,日积月累,很多关于C的疑惑在书本和资料中都难以找到答案。程序员是追求完美的一个种群,其头脑中哪怕是存在一点点的思维黑洞都会让其坐卧不宁。不久前在itput论坛上偶得《Computer Systems A Programmer’s Perspective》(以下称CSAPP)这本经典好书,遂连夜拜读以求解惑。虽说书中没有能正面的回答我的一些疑惑,但是它却为我指明了一条通向“无惑”之路 — 这就是打开汇编之门。 ...
在Java、C++和C#等高级语言的单元测试正进行的如火如荼的时候,C好像做了看客,冷清的躲在了一个不起眼的角落里。C并不是没有单元测试工具,像Check和CUnit这样的工具也很有名气,只是和大名鼎鼎的JUnit比起来,还是显得有些英雄气短。很多大型的C项目,如APR等都没有使用像Check、CUnit这样通用的单元测试框架,而是另起炉灶自己编写。其实编写一个仅能满足单个项目需要的C单元测试工具包并非难事。在部分参考APR的ABTS的前提下,我们也来设计一套自己的简单的C语言单元测试包。 鉴于减少复杂性,我们的目标仅仅是设计和实现一套能在单进程、单线程下工作良好的C单元测试包,我们暂且将之命名为CUT – C Unit test Toolkit。 1、CUT涉及的术语解释 曾经接触过多个有名的单元测试框架如JUnit、CppUnit、TestNG等,它们在对单元测试某些概念的理解上并不是全都一样的。这里我们也有我们自己的定义。 a) 一个逻辑unit test包含至少一个或者多个suite; b) 一个suite包含至少0或者多个test case; c) 每个test case中至少包含1个或者多个“断言类”语句。 ...
APR中少见对数据结构的封装,好像唯一例外的就是其对循环链表,即环(RING)的封装。 在大学的时候学的不是计算机专业,但大三的时候我所学的专业曾开过一门好像叫“计算机软件开发基础”的课,使用的是清华的一本教材,课程的内容包括数据结构。说实话听过几节课,那个老师讲的还不错,只是由于课程目标所限,没讲那么深罢了。当然我接触数据结构要早于这门课的开课时间。早在大一下学期就开始到计算机专业旁听“数据结构”,再说一次实话,虽号称名校名专业,但是那个老师的讲课水平却不敢恭维。 ...
离我的上一篇BLOG已经时隔一个月有余,项目忙是一方面原因,最主要的还是自己没什么“收获”。在最近的项目中总是和内存打交道,时间长了,便有了些许问题,原本我就不是不求甚解者,遂趁此机会又复习了些内存相关资料。 ...
一次Sun SPARC到Intel X86的平台移植让我们的程序遭遇了“字节序问题”,既然遇到了也就不妨深入的学习一下。 一、字节序定义 字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。 ...
共享内存是一种重要的IPC方式。在项目中多次用到共享内存,只是用而并未深入研究。这次趁研究APR代码的机会复习了共享内存的相关资料。 APR共享内存封装的源代码的位置在$(APR_HOME)/shmem目录下,本篇blog着重分析unix子目录下的shm.c文件内容,其相应头文件为$(APR_HOME)/include/apr_shm.h。 ...
Unix提供了等待信号的系统调用,sigsuspend就是其中一个,在CU(www.chinaunix.net)上曾经讨论过一个关于该系统调用的问题,这里也做一下解疑。 CU网友讨论的问题的核心就是到底sigsuspend先返回还是signal handler先返回。这个问题Stevens在《Unix环境高级编程》一书中是如是回答的“If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend.”,由于sigsuspend是原子操作,所以这句给人的感觉就是先调用signal handler先返回,然后sigsuspend再返回。但其第一个例子这么讲又说不通,看下面的代码: CU上讨论该问题起于中的该例子: int main(void) { sigset_t newmask, oldmask, zeromask; ...
潜水于CU(www.chinaunix.net),看到了大家对Zombie Process和Daemon Process的理解,同样也意识到以前自己对这两个概念理解的偏颇,想在这篇Blog中将之纠正。 一、Zombie Process Zombie Process,译成中文为僵尸进程,以前我一直认为父进程先结束,子进程就变成了僵尸进程,事实上这与正确的理解恰恰相反,真惭愧,只是从字面理解了而并未深入研究。下面重新理解一下: ...
看到ChinaUnix(CU)上的一个帖子后,觉得自己对dup和dup2特别是后者的理解还是有欠缺的,这两个接口看起来很简单,但是理解起来也真的并不是那么容易。 相信大部分在Unix/Linux下编程的程序员手头上都有《Unix环境高级编程》(APUE)这本超级经典巨著。作者在该书中讲解dup/dup2之前曾经讲过“文件共享”,这对理解dup/dup2还是很有帮助的。这里做简单摘录以备在后面的分析中使用: Stevens said: (1) 每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表,可将视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是: (a) 文件描述符标志。 (b) 指向一个文件表项的指针。 (2) 内核为所有打开文件维持一张文件表。每个文件表项包含: (a) 文件状态标志(读、写、增写、同步、非阻塞等)。 (b) 当前文件位移量。 (c) 指向该文件v节点表项的指针。 图示: 文件描述符表 ———— fd0 0 | p0 ————-> 文件表0 ———> vnode0 ———— fd1 1 | p1 ————-> 文件表1 ———> vnode1 ———— fd2 2 | p2 ———— fd3 3 | p3 ———— … … … … ———— ...