读书人

Linux上C++开发初探

发布时间: 2012-10-12 10:17:04 作者: rapoo

Linux下C++开发初探
处理后会产生一个可以供 Autoconf 使用的 Makefile.in文件。再配合利用 Autoconf产生的自动培植设置文件 configure 即可产生一份符合符合 GNU Makefile 惯例的 Makeifle 了。

?????? automake的基本用法,是先用autoscan搜索当前目录,然后形成一个configure.scan文件,然后以configure.scan文件为蓝本,形成一个configure.in文件,这是最终需要的文件。然后使用aclocal处理一下本地的宏,再使用autoconf生成一个configure脚本文件。configure脚本文件用来形成最终的makefile。之后编译一个Makefile.am,定义automake需要的一些宏,包括源文件列表等。执行automake,形成Makefile.in文件。这样,需要的准备工作基本完成。编译的时候,通过执行configure脚本,会自动生成Makefile文件,然后再执行make就可以了。

?????? 关于automake的详细用法请查看参考资料。

2.3 运行和调试

跟Windows不统,Linux下面的文件只有有可执行的权限就可以执行,不像Windows那样依赖于扩展名。所以Linux下的执行程序大都没有扩展名,任何文件只要给了一个执行权限,就可以直接运行。可以通过chmod +x来给一个文件增加可执行的权限。编译后形成的目标文件,通常都已经有了执行的权限,所以可以直接执行。

2.3.1? 设置运行环境

对于简单的程序来说,不用设置什么运行环境,直接运行即可。对于负责的程序来讲,可能执行程序和需要的共享库文件不在同一个目录下,就需要设置一些运行环境了。设置运行环境主要就是设置共享库的路径。Linux下的共享库,相当于Windows下面的动态库(dll文件),是一种以.so为扩展名的文件。系统的共享库存放在/usr/lib下面,程序运行的时候会自动去那个目录下面寻找需要的共享库。对于用户自己开发的共享库,一般不能放在/usr/lib目录下面,而是放在用户的程序目录下面。一个 比较复杂的程序,其目录结构分的比较清晰,并不是把所有的文件都放在一个目录下面。下面列出了一个典型的目录结构:

mainpath?????????????? 程序主目录

mainpath/bin????????? 执行程序目录

mainpath/lib?????????? 共享库目录

这种情况下,就需要设置程序的运行环境,指定库文件目录。设置运行环境其实就是在运行程序前设置若干个环境变量,其中共享库的路径就是其中之一,也可一设置一些程序需要的其他的环境变量。Linux下面用LD_LIBRARY_PATH来表示用户共享库的路径。设置完环境变量,就可以运行程序了。

有一种更方便的方法,就是编写执行脚本。Linux下面的脚本相当于Windows下的批处理文件,就是执行一系列的命令。本质上来说,脚本文件就是一个文本文件,编辑完成后增加一个可执行权限即可。在Linux下面的终端窗口,都是基于外壳(shell)的。在Linux中大家最常使用Bourne?Shell以及C?Shell?,系统默认采用的是Bourne?Shell。不同的shell有不同的编程语言,也就是说编写shell脚本的语言,用来实现一些更高级的功能。在脚本中,可以指定本脚本采用的语言。关于shell编程的详细信息,请查阅参考资料。一般情况下,Bourne?Shell脚本文件以.sh为扩展名,C Shell脚本文件以.csh为扩展名。这里我们以Bourne?Shell为例。

一个典型的程序目录中,一般存在3个脚本:执行脚本(run.sh)、停止进程脚本(kill.sh)和设置环境脚本(setenv.sh)。脚本文件一般都放在程序的主目录下面,进入主目录可以直接通过这些脚本来执行程序。下面简单列出了这几个脚本的内容。

setenv.sh:

?????? #!/bin/sh

path=`pwd`

LD_LIBRARY_PATH=$path/lib:$LD_LIBRARY_PATH

export LD_LIBRARY_PATH

??????

run.sh:

?????? #!/bin/sh

path=`pwd`

LD_LIBRARY_PATH=$path/lib:$LD_LIBRARY_PATH

export LD_LIBRARY_PATH

cd bin

./demo

cd ..

??????

?????? kill.sh:

#!/usr/bin/sh

for sid in `ps -e |grep demo |awk {'print $1'}`

do

kill $sid

done

??????

?????? 值得注意的一点是,外壳其实也是一个进程,运行脚本以后会创建一个新的进程。环境变量依赖于进程,也就是说脚本里面设置的环境变量在脚本完成后将会消失,不回影响外壳进程和其他进程。也就是说,正常情况下我们的setenv.sh相当于不起任何作用。不过可以通过另一种执行方法来保留脚本执行过程中设置的环境变量,即“. setenv.sh”。其实就是在执行命令的前面加上一个‘.’和空格。这样脚本中设置的环境变量就会作用域执行这个脚本的外壳进程,也会影响到以后在这个外壳下面运行的所有进程。

2.3.2? 使用调试工具进行调试

程序的调试,是程序开发中最重要的一部分,通过调试来找到程序中的bug。Linux面的程序调试工具有很多,包括IDE环境下的调试工具和字符界面的调试工具。这里我们主要介绍字符界面的调试工具。常用的调是工具是dbx,大部分Linux系统下都有。在linux下面,调试工具为gdb,功能跟dbx类似。

跟Windows类似,要以调试方式运行程序,就必须按照debug版来编译程序。Linux下面的编译一一般通过-g参数来声明使用debug方式进行编译,这样编译后的目标文件中就包含了源代码的信息。下面以gdb为例,介绍一下Linux下面程序调试的基本方法。

1)??????? 以调试方式运行程序

在执行程序所在的目录下,执行gdb,以程序名称为参数即可进入gdb调试界面。如:gdb demo

2)??????? 查看源文件,设置断点

在gdb下,使用list命令可以查看主函数所在的文件的内容。默认情况下,一次显示10行内容,再次执行list可以显示后面的10行。

确定要在哪行上设置断点,然后用break命令进行断点设置。如:

break 10 表示在第10行上设置一个断点。

break命令还可以指定要设置断点的文件(如果不是主函数所在的文件),如:

break func.cpp:10 表示在func.cpp的第10行上设置一个断点。

除了在具体的行上设置断点外,还可以在某个函数上设置断点,只要把行号换成函数名即可。

clear命令用来清楚当前行的断点,delete命令可以删除所有设置的断点。

3)??????? 运行程序

设置完断点后,可以在gdb下通过run命令运行程序,如果程序需要什么参数,直接放在run命令后即可,如:

run start

其中-start是程序允许需要的一个参数。

4)??????? 断点处程序分析

当程序执行到断点的时候,就会定下来等待用户进行处理,这是可以通过一些命令来查看程序当前的运行状态,这些命令包括:

print??????? 打印变量的值,只需要用变量名做命令参数即可

where???? 显示程序当前的调用栈

set variable 改变变量的值,可能会影响到程序后面运行的结果

5)??????? 单步调试

在断点处处理完成后,可以继续往下执行程序,next命令用来执行一行代码,step命令用来跟踪到即将执行的函数中。continue命令可以继续运行当前程序,直到遇到下一个断点。

?????? 上述流程中,简单介绍了一些如何使用使用gdb来进行程序的调试。gdb中的所有命令,都可以用简写来表示,只要写道能够区分处改命令的字母数即可,比如可以简单的输入n表示next命令。除了上面介绍的命令外,还有很多有用的命令。attach和detach命令,可以在程序正常运行的情况下把gdb帮定到一个进程中,进行调试,调试结束后恢复正常的程序运行,推出gdb对程序运行没有影响;pwd命令可以显示当前的工作目录,cd命令可以改变当前的工作目录;thread命令可以查看当前的线程ID。还有很多别的命令,可以通过help命令获得详细的帮助信息。

?????? 除了dbx和gdb外,Linux下面还有很多调试工具,详细信息请看参考资料。

2.3.3? core dump

对于Linux开发人员来说,core dump是再熟悉不过的了。在Linux下面,core dump就是程序bug的最严重的体现。core dump又叫核心转储,当程序运行过程中发生异常,程序以外退出的时候,系统会把程序当前的内存状况存储在一个core文件中,就叫core dump。

既然core文件记录了程序运行时的情况,就可以通过core文件来分析错误的原因。使用gdb/dbx 运行程序名 core就可以把程序恢复到发生错误的哪一时刻,可以看到程序在执行哪行代码,调用什么函数时发生了错误。这是,可以借助调试工具的其他命令进行更细致的分析。个人觉得,Solaris下实现的dbx远比gdb强大的多,可以看到更多的信息。

值得注意的是,在linux下面有一个系统限制,就是core文件的大小。如果这个限制设成0,则程序发生异常以后不回产生core文件。如果想得到core文件,请使用ulimit c命令来调整这个参数。ulimit a命令可以查看到系统当前的限制参数情况。

3. 常用命令介绍

Linux下面的常用命令,跟Windows下的控制台命令有很大差别。Linux下的命令,可能是一个执行程序,或者一个可以执行的脚本,系统的命令一般都可以在/usr/bin/下面找到。另外需要说明的一点,Linux下面严格区分文件名的大小写,包括命令的大小写。下面简单介绍一下Linux系统下常用的几个命令。

3.1 常用命令列表

ls???????????? 列出当前目录下的文件,相当于Windows的dir。

cd??????????? 切换目录,和Windows下的cd命令相同。

mkdir?????? 创建一个目录。

rm?????????? 删除一个文件或者目录。-r参数表示删除的是目录,-f参数表示强制删除。

mv?????????? 移动或者修改文件/目录名称。

cp??????????? 拷贝文件或目录,-r参数表示拷贝的对象是目录。

ps??????????? 查看当前系统的进程情况,-e是最常用的一个参数,表示列出所有进程。

man??????????????? 查看手册,这是一个最常用的命令,通过他可以查看指定命令或者函数的使用手册。比如man ps就可以产看ps命令的帮助手册,man fopen可以查看fopen函数的用法。

find????????? 在指定目录下查找指定的文件。

grep???????? 在指定文件中查找指定的内容。

vi???????????? 编辑文本文件,后面会做详细的介绍。

tar?????????? 文件打包和解包工具,通过cvf参数打包,通过xvf解包

gzip??????????????? 压缩工具,可以把文件压缩成gz文件,通过-d参数进行解压缩,常于tar命令一起使用。

3.2 命令的组合

在Linux下面,可以把多个命令组合使用,可以把一个命令的执行结果作为另一个命令的输入。其中,最常跟别的命令组合使用的命令就是grep。在2.3.1中的那个kill.sh脚本中,我们就使用了这样一个组合命令“ps -e |grep demo |awk {'print $1'}”,用来列出当前系统中所有名称为demo的进程的进程号。这种用法是我们开发过程中最常用的方法。另外如果我们想知道我们的程序的网络情况,可以通过netstat命令和grep命令来组合使用,获得指定端口的状态情况,比如netstat a | grep 43001,这个命令将列出当前系统中所有在端口43001上的连接情况。

通常的grep命令,只能查找当前目录下的文件,比如:grep ‘OPEN_MAX’ *.h 就是查找当前目录下面的所有头文件中是否含有“OPEN_MAX”这个词。而find命令可以查找指定路径下面的所有子目录,发现所有匹配的文件,那么,我们就可以用grep命令和find命令组合,来实现子目录下的文件内容查找。命令格式如下:

grep 'OPEN_MAX' `find /usr/include -name '*.h'`

这样可以查找所有在/usr/include及其子目录下的头文件,看是否包含“OPEN_MAX”。执行的时候,先执行find命令,形成一个文件列表,然后把这个文件列表作为grep的一个参数来执行grep命令。这是命令组合的另一种方式。

读书人网 >C++

热点推荐