linux 下 C 编程和make的方法 (六:一个C模块的实现)

我们就先做个tree 模块吧,这里说下讲TREE的理由,很简单,如下 
    1、tree相对复杂点,我就说个堆栈,恐怕可以展开的东西不多。 
    2、正在把文件生命周期管理的中间件进行开源。正好用tree开刀。 
    3、tree好啊,文件夹里大把天然的测试数据,我省得造数据的麻烦了。 
    4、不是菜鸟经常被别人说“去看内核源码”,那好吧,既然你们总被喷,不如咱们也从tree展开,等到最后,听完,也算对linux内核的vfs有所了解。野鬼不带新手逛点带彩的地方,怎么能算“成年”呢。你不自个逛那是因为你太害羞而已。 
    
    这里谈一下tree的数据结构的一些基本特性。也就是啥是树。图论书籍中有非常科学严谨的解释。我这弱智的说说。什么算是一个树。 
    1、一群个体,相互有血缘关系。血缘关系只有一种,父子关系。 
    2、任何一个个体,只有一个老爸,且必须要有个老爸。 
    就这么简单。有人说你胡扯,树的根,他就没有老爸。哈。不妨我反驳你,首先,树有个性质,从图论中说。就是加上任意条边,则构成环。当然自己指向自己的边 这个不能算。因为这不是个朴素的图。如果自己指向自己的也算边,你的图可平面时,你就无法使用平面图上很多理论。 
    我的定义:朴素图是,边是特指连接两个不同的顶点。就是说关系,仅指两个不同的个体之间的关联。 
    如果这么说,那么对于一个树而言,只存在一个根的时候,就麻烦了。怎么加边呢? 

    所以对于树而言,理论上是不存在只有一个顶点的情况。即便就是一个根,自然会出现两个顶点。只不过根指向一个没有任何意义的顶点,如同我们编写代码是,指针指向0,表示没有意义,但不代表这个0不存在。 
    废话不多,我们开始上代码。不过上之前允许我再废话一下。我们要建目录了。执行如下命令: 
1 $mkdir data_struct
2 $cd data_struct
3 $mkdir inc
4 $mkdir src
5 $mkdir bin
6 $mkdir obj

    为什么是data_struct,模块化的思想啦,很多结构,结构套结构的。我一层层的包起来,当面向对象啊?所以干脆data_struct库吧。以后涉及抽象数据结构的,都装里面。当然为了说明学习C而涉及。如果linux下有类似模块,我们本着 绝不重复开发的原则,还是坚持用别人已经开放的模块使用。 

1 $cd src
2 $:>ds_tree.c
3 $scribes ds_tree.c //为啥用这个名字,还好还好,google一下这个名字没有太多信息,省得与其他库C文件名冲突
如下编辑 
01 /***************
02 src/ds_tree.c
03  by luckystar
04  ***************/
05 static int ds_tree_flag =0;
06  
07 void ds_tree_init(void){
08     if (ds_tree_flag) {
09         //log("module inited..",X);
10         return;
11     }
12     ds_tree_flag = 1;
13     //todo:module init...
14  
15 }
16  
17 void ds_tree_destory(void){
18     if (!ds_tree_flag) {
19         //log("module not inited..",X);
20         return;
21     }
22     ds_tree_flag = 0;
23     //todo:module destory...
24  
25 }
保存退出,若问这是啥,别废话,敲你的键盘。 
1 $cd ..\inc
2 $:>ds_tree.h
3 $sciribes ds_tree.h
如下编辑 
01 #ifndef _ds_tree_H_
02 #define _ds_tree_H_
03  
04 //ins_inc_file
05  
06 //ins_typedef_def
07  
08 //ins_def
09  
10 //ins_func_declare
11  
12  
13 #endif //_ds_tree_H_
保存退出 
1 $cd ..\src
2 $:>ds_tree.c
3 $scribes test_ds_tree_main.c //只是测试代码以后不用
如下编辑 
1 #include <stdio.h>
2 #include "ds_tree.h"
3 //extern void ds_tree_init(void); //你可以尝试打开这个注释,看有什么变化,回答没有
4 int main(int argc,char*argv[]){
5     ds_tree_init();
6     ds_tree_destory();
7     return 0;
8 }
保存退出 
1 $cd ..
2 $:>Makefile
3 $scribes Makefile
如下编辑 
01 .PNONY:build_lib
02 build_lib:bin/libds_tree.a
03 bin/libds_tree.a:obj/ds_tree.o
04     ar -r bin/libds_tree.a obj/ds_tree.o
05 obj/ds_tree.o:src/ds_tree.c inc/ds_tree.h
06     gcc -fpic -Iinc  -c src/ds_tree.c -o obj/ds_tree.o
07     
08 .PNONY:test  
09 test:bin/test
10 bin/test:bin/libds_tree.a obj/test_ds_tree_main.o
11     gcc obj/test_ds_tree_main.o -Lbin -lds_tree -o bin/test
12 #test
13 #    gcc  -Lbin -lds_tree obj/test_ds_tree_main.o -o bin/test
14 # you will not found func
15 obj/test_ds_tree_main.o:src/test_ds_tree_main.c inc/ds_tree.h
16     gcc  -Iinc -c src/test_ds_tree_main.c  -o obj/test_ds_tree_main.o
17     
18 .PNONY:clean
19 clean:
20     -rmobj/*.o       
21     -rm bin/*
保存退出//这里的makefile仍然弱智版的,我们不进化,一个章节只谈一个方向的问题。以后专门进化。 
 
1 $make test
2 $./bin/test

  
看看出来啥东西。 
OK。收工!!! 

    估计有人要扁我了。"这和tree有个毛关系啊。啥代码都没有。"

    我的回答很简单。你如果是新手,记得上面的每个步骤,和第一次编译前,做且仅做的内容。那上面的事情都是啥?

    这叫“搭窝”,只有make过了,可以执行了,才表示你可以开发了。便便还要找蹲坑,找呢,当然我是说大的。记得第一次编译前,只做这么多。这叫"缩小开发反馈环大法"

由于咱们第一次讲linux下编写C程序,是和tree没关系,但和编写代码有关系。所以收工。当然收工前,提醒一下,关注以下内容并收集资料。

1、ar 命令,是用于将多个obj文件,归档到一个.a,也就是通常说的静态库的。 
但起名字很关键。你要注意到make 里 bin/test的操作(还好是弱智版的,我要增加变量,就难解释了),这里有个 -Lbin ,这个意思是增加指定的库所在的路径。但这个-L只对-l(小写的L)有影响。 -l有什么用呢?和-Lbin组合起来就等于 bin/lib,他会把库文件前面 lib的前缀自动省去,同时某默认对.a文件而言,.a不需要书写,简化你的工作。当然你可以如下做 
1 ar -r bin/ds_tree.a obj/ds_tree.o
这看起来很微软。其实无所谓。但是你对这个.a的使用,得如下 
1 gcc obj/test_ds_tree_main.o bin/ds_tree.a -o bin/test
你需要给出全名。你可以试下 
1 gcc obj/test_ds_tree_main.o bin/ds_tree -o bin/test
肯定不对啦。如果 bin/真有个ds_tree的文件怎么办? 
估计有新手会说了,bin/ds_tree.a 明显比-Lbin -lds_tree 要少,我毛病要用你的-L -l的方式啊,还要在确保库是以lib打头的,如ds_tree的库为 libds_tree.a 
哦。我没有意见,但你别忘了,每个库文件都有路径,每个库文件都有 .a要明确写出来。如果你有10个库文件,貌似 -L -l就更快了。这些先进的玩意是给大工程用的,如果你偏要用自己的库文件名的话,我没意见,反正(弱智版嘛)。 
2、在ds_tree.c和Makefile里都有一些错误操作。你可以试试,体会下gcc的命令的原理。 
3、对比下这个Makefile和前面的Makefile有什么不同了。显然不是少了 build all。为什么不把test,放在第一个。 
4、哦,对了,最后说一下,最后的正确执行结果就是  啥结果都没有 。不用吐,现在吐光了,后面还有更值得你要吐血的。 

好,真收工了。

转自:http://my.oschina.net/luckystar/blog/67081

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值