linux程序开发如何入门

76次阅读
没有评论

共计 7862 个字符,预计需要花费 20 分钟才能阅读完成。

今天就跟大家聊聊有关 linux 程序开发如何入门,可能很多人都不太了解,为了让大家更加了解,丸趣 TV 小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

总会看到有人说 Linux 上的应用程序开发是高手才可以完成的,而且这种“迷信”在目前似乎还很普遍。然而,情况并不是这样的,从程序库的支持方面,Linux 平台为用户级应用程序的开发提供了很多功能强大且丰富的程序库,而且它们大部分是跨平台的(Boost、OpenGL、STL、Qt、Java 等)和基于 POSIX 标准的(glibc 等),同时 Linux 内核还为驱动程序的开发提供了功能完备的内核接口,从开发工具方面,Linux 提供了功能强大的编译器 GCC 和调试器 GDB,借助它们的帮助,我们可以很轻松的在 Linu x 上开发出可移植性的应用程序。既然如此,“迷信”又源于何来呢?我想,一方面由于详细介绍 Linux 各种开发的书籍较少,各种 Linux 应用在国内仍不普及,另一方面则是由于很多人在安装好一个 Linux 后,苦于找不到一个得心应手的 IDE 环境,从而感到不知所措,毕竟,我们很多人都习惯了写好程序后,按下 F5,剩下的任务就让 IDE 全权代理了。其实想在 Linux 下如此这般当然也没问题。既然说到了 IDE,就让我们从它开始吧,相信选择一个好的 IDE 环境是你整个学习过程的一个不错的开始。

工欲善其事必先利其器——IDE 篇

其实 Linux 下有许多功能强大的 IDE 环境,因为从某种意义上说,Linux 是专为开发者准备的操作系统,这个东西当然少不了,在这里为读者介绍一些比较常用的 IDE。

KDevelop

这是一个用 Qt 开发的 IDE,其主要支持的语言是 C / C++,

Eclipse

近年来,eclipse 可以说发展极为迅速,它不仅是一个以 java 为主的开发平台,其功能强大的插件体系结构使得它可以被当作各种应用程序来使用。作为各种插件的载体,eclipse 提供了完整的 GUI 接口,用户完全可以借助 eclipse 来只关心自己想做的工作。

Emacs

VIM

山高月晓水落石出——IDE 后台的故事 GCC 篇

前面我们简要介绍了一些 IDE 环境,其中所有 C /C++ 相关程序的编译都是由 GCC 来完成的,而 IDE 只不过起到了一个收集编译信息和为我们的项目生成 makefile 等作用(后面我们会提到)。出于目前 Linux 开发的特点,C 仍是系统开发的主流语言。所以,对 GCC 有一个全面的了解是很有必要的,一旦 IDE 不能满足你的需求,我们要有手工打造程序的能力,而且出于学习的目的,我们往往不需要 IDE 生成的那些复杂的文件,为一个 Hello world 生成 2M 多的文件显然是多余的。

GCC 的全称是 GNU Compiler Collection,从这个名字我们不难看出,GCC 代表着一个编译器的集合,目前 GCC 可以支持 C, C++, Objective-C, Objective-C++, Fortran, Java, and Ada 等语言。但是出于一般性考虑,我们这里只讨论 GCC 中的 C /C++ 部分。

目前 GCC 的 *** 发布版是 4.0.0,但是这个版本由于使用了新技术和新的编码规范,很多旧的代码都需要修改才可以通过编译,所以并不推荐使用这个版本。而相对稳定的新版本目前是 3.4.4,大家可以到 GNU 的主页上更新下载。那么究竟 GCC 强大在哪里,如何使用?下面我就通过几个简单而实际的例子带你看看 GCC 提供的强大功能。

通过 Helloworld 的编译熟悉 GCC 的基本使用方法

似乎为所有新语言提供一个 Hello World 样本程序已经成为了一种不成文的标准,人们通过它来认识语言的一些基本要素。在这里,我们使用一个 Hello World 来看看如何用 GCC 生成可执行文件。

把上面的文件存成 helloworld.c,之后打开控制台,输入如下的命令 gcc helloworld.c –o helloworld 如果一切正常的话,你的控制台上应该没有任何输出。用 ls 查看你的工作目录,你会发现目录下多了一个名为 helloworld 的可执行文件,之后,执行./hellworld

就会看到这个程序的输出了

很简单不是吗?但是学过计算机的朋友都应该知道,程序的编译过程要分为下图所示的过程而 GCC 的强大之处就在于它允许你在上面所示的任何一个过程中停下来查看中间结果,并对其加以控制。

1. 预处理首先是预处理过程,GCC 的 - E 选项可以让 GCC 在预处理后停止编译,并向标准输出打印预处理过后的文件。下面的 - o 用于指定输出文件的文件名。

gcc –E hellowrold.c –o helloworld.cpp 下面是 helloworld.cpp 的一部分的内容,我们看到,文件已经包含了 stdio.h 中的内容。

如果我们想执行下一步的编译过程,可以继续使用 GCC 的 - x 选项,该选项用于显示指定文件的后缀名(而不是让编译器根据后缀来自行判断)。我们比较常用的 language type 有如下几种,(如果读者想获得更为完整参数说名,请参考 GCC manual):

l c c-header c-cpp-output

l c++ c++-header c++-cpp-output

l assembler assembler-with-cpp

另外,下表列出了常用的 GCC 后缀名

当然,你也可以省略掉 language type 的部分,这时候 GCC 会根据文件的后缀名自行判断,就像你没有使用该选项一样。

下面继续我们的编译过程

2. 编译如果我们想获得编译后的源文件可以使用 - S 选项,该选项让 gcc 只执行编译(生成汇编文件)而不进行汇编(生成目标文件), 此时,我们可以用 - o 选项指定输出的汇编文件的名称。

gcc –S helloworld.cpp –o hellowrld.S

3. 汇编另外,我们还可以使用 GCC 的 - c 选项来编译和汇编源文件而不链接,此时 - o 指定的输出文件就是编译后的目标文件名 gcc –x c++ -c helloworld.cpp –o helloworld.o

4. 链接 ***,我们可以利用 GCC 来把我们刚才生成的.o 文件链接成可执行程序 gcc helloworld.o –o helloworld 这一次,我们使用了 - o 选项指定了可执行文件名,也就是说,根据输入文件类型的不同,- o 有着不同的含义。

5. 函数库的链接和包含文件对于我们编写的任和一个程序,没有库函数的支持是不可想象的,而当我们要使用的头文件和函数库不在 GCC 默认的搜索路径下的时候(例如 OpenGL、Qt、KDE、Boost 等),我们就需要手工来告诉 GCC 他们的位置。

先来看头文件路径的指定。我们可以利用 - I 来指定我们希望 GCC 去搜索的头文件目录,例如我们要使用 X11 的程序,我们就要使用下面的选项再来看库函数的设置:我们通过 - L 和 - l 两个命令行选项完成任务。其中 - L 用于告诉 GCC 在中去寻找函数库,而 - l 选项则告诉 GCC 使用用户指定的程序库。在 Linux 中,函数库的命名是遵循 UNIX 约定的,即 lib{lib name},例如 libsocket.so,所以当你需要告诉 GCC 使用这些库的时候,你就可以使用 -lsocket 选项。通常,这两个命令是结合在一起使用的,例如引用 X11 程序库的时候,我们可以这样:

–L/usr/X11R6/lib–lX11

另外,GCC 在默认情况下使用共享库来链接程序,而当你想链接静态库的时候,一定要使用 -static 选项,例如 -lncurses -static

在这一部分的 ***,我们对编译时用到的 GCC 常用命令做一个简要的总结

上面,我们提到了关于 GCC 编译的常用命令,这里另外补充一些帮助性的常用命令,他们可以让你对 GCC 的基本配置和使用作一个了解。

在这部分的 ***,我们来谈一谈关于构建软件时链接参数的设定问题。在上面的第 5 部分我们已经提到了,函数库的使用是需要 - L 和 - l 一起配合来使用的,但实际上,往往一个像样的程序需要很多库的支持,例如,如果你需要编写一个 GTK 程序,我们需要下面的链接参数:-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 –lm,看上去有些吓人,你可能会问,我如何知道需要这些呢,如果我想编写 KDE 的程序呢,还有 OpenGL 呢?其实,情况比你想象的要好很多,在 /usr/bin 目录下,有很多名为 xxx-config 的脚本,它们的作用就是向用户显示编译链接程序时使用的参数的。这些脚本可以接受一些参数,比较常用的有—libs 用于列出链接特定程序时使用的程序库,另外 –cflags 用于生成头文件的包含目录,也就是上面我们提到的 - I 参数。于是,对于 GTK 程序,我们可以使用下面的命令来编译:gcc gtksource.c `gtk-config –libs –cflags` 当然,为每一种程序写一个 config 显然不是一个好办法,目前新的开发包都使用 pkg-config 这个脚本来生成链接参数。你可以使用 pkg-config –list-all 查看 pkg-config 支持的所有链接参数当你在上面这份列表中查到了自己想要程序包时,就可以使用下面的命令来编译程序了 gcc.suffix `pkg-config

–libs –cflags`

让 GCC 帮助你更好的工作

上面我们简单介绍了 GCC 的常用命令行选项,其实 GCC 的功能比上面提到的那些要丰富得多,GCC 对代码的警告、优化、调试等方面提供了丰富的支持,下面我们就从一些例子来看看 GCC 提供的这些功能。

1.对问题代码提出警告

GCC 对程序代码提供了完整的检查功能,由于 C /C++ 语言本身的特点,很多错误都是程序员无意间犯下的,例如使用了未定义的变量、在 bool 表达式中使用了 = 而不是 == 等等问题,利用 GCC 提供的代码检查功能,我们可以让编译器为我们找到这些问题,避免运行时发生灾难。

首先,我们来看一个“问题代码”

/* test_warning.c We use this file to check the warning facilities provided by GCC*/ #include#include

void main() { /* main should return int*/

int a, b; long long l = 2.2; /* long long type is GNU extension, not standard ANSI / ISO type*/

miss_decl(); /* We call an undeclared function*/

if (a = 0) /* May be we want == here instead of =*/

printf (“a really equals to 0?\n”); if (b != 0)  /* We used uninitialized variables*/ /* %d and“We should put b here”don‘t match*/ printf(“We make a mistake again! b = %d\n”,“We should put b here”);

};

void miss_decl() {

/* /* This type of annotation is prohibited*/

printf(“We should put the declaration before it‘s been used!\n”);

}

上面这些代码故意制造了很多编程中出现的常见问题,接下来,我们就用这段代码来检测一下 GCC 提供的各种常用的警告设施。

首先,我们不使用任何警告设施编译上面的程序 gcc test_warning.c –o test_warning 默认情况下,GCC 会给出输出,其中 GCC 识别出了 main 函数不标准(warning)以及使用了未声明的函数(error)两个问题,但是其他的 GCC 并未察觉。

1.利用 -pedantic 找出不符合 ANSI / ISO 标准的代码

执行下面的命令:gcc –pedantic test_warning.c –o test_warning 可以看到,这次 GCC 以警告的形式报告了代码中 long long 的使用,但是要说明的是我们并不能依赖这个选项来保证我们的代码完全符合 ANSI / ISO 标准,因为该选项只报告 ANSI C 要求编译器进行检察的内容。另外,你还可以使用 -pedantic-errors 让 GCC 把所有的警告都变成错误。

2. 利用 -Wformat 检查 printf 中的参数不匹配问题执行下面的命令:gcc –Wformat test_warning.c –o test_warning

3. 利用 -WComment 找出注释中的错误执行下面的命令:gcc –WComment test_warning.c –o test_warning

4. 利用 -Wparentheses 查找 bool 表达式中的 = 错误执行下面的命令:gcc –Wparentheses test_warning.c –o test_warning

5. 用 -Wuninitialized 查找未初始化变量的使用执行下面的命令:gcc –O –Wuninitialized test_warning.c –o test_warning 值得说明的是,在使用这个选项的时候,一定要配合上 -O(后面我们会提到) 选项

6. 利用 -Wimplicit-function-declaration / -Werror-implicit-function-declaration 检查未声明函数的使用执行下面的命令:gcc -Wimplicit-function-declaration test_warning.c –o test_warning 另外 -Werror-implicit-function-declaration 和 -Wimplicit-function-declaration 作用是类似的,只是如果你使用了未声明的函数,前者会把它认为是一个错误。

7. 如果你只是想对你的代码进行全面的检查,你大可不必把上面的选项一并列出来,GCC 提供了 -Wall 选项,含义就是列出所有代码中的警告执行下面的命令:gcc –Wall test_warning.c –o test_warning 8. 如果你想走另一个极端,也就是不想让 gcc 输出任何警告,那么使用 - w 选项,该选项禁止所有的警告执行下面的命令:gcc –w test_warning.c –o test_warnin

输出结果

对于上面所有的选项,你都可以把它们和 -Werror 选项一起使用,这样就可以把所有的警告都变成错误。另外,如果你只是想对代码进行检查而并不执行编译的话,可使用 -fsyntax-only 选项,像下面的命令这样 gcc –fsyntax-only test_warning.c 基本上来说,我们常用的一些警告选项就是这些,而其中 -Wall 更是我们极为常用的功能。

2. 优化选项这一部分的内容可以分成两部分,一部分是让编译器对代码进行分析

后,进行的代码优化,另一部分是我们可以为编译器制定一些关于硬件的信息,让他生成对硬件结合的更好的代码,而我们之所以要用源代码来编译程序,很多情况下,是出于这方面的原因。

首先来看代码优化,从代码的整体优化上,GCC 提供了下面的选项

-O–O1

这两个选项的含义是一样的,GCC 将执行减少代码尺寸和执行时间的优化,对于那些会严重影响编译时间的优化选项,这个级别的优化并不会执行。

-O2

在这一级别 GCC 将会提供所有支持的优化,但这其中并不包括以空间换时间的优化手段,例如编译器不会使用循环展开和函数内联。和 - O 相比,该选项进一步加快了编译时间和生成代码的性能。

-O3

除了 -O2 提供的优化选项外,还指定了 -finline-functions,-funswitch-loops 和 -fgcse-afer-reload 选项,目的只有一个就是全力执行代码优化。

-Os

这个选项是专门用来优化代码尺寸的,-Os 打开了所有 -O2 级别中不会显著增长代码尺寸的优化选项

-O0

该选项代表不执行优化

在这里要说明的是,尽管 GCC 提供了 1~3 和 s 这 4 个整体优化选项,但从实际的优化效果上来看,往往 O3 优化出来的程序的效率并不是 *** 的,而大部分情况下我们都在使用 -O2,如果你希望获得 *** 的效率利益,那么不妨这 4 个选项都试试。另外,其实这些选项只不过是 GCC 提供的很多单方面优化的一个组合,如果你想了解更为具体的优化内容,可以去查看 GCC 手册,出于篇幅限制,这里不细谈了。*** 要记住的一点是,如果你的程序是用于高精度数值计算的,那么记住不要使用上面任何的优化选项。

下面来看基于硬件优化,由于这部分和计算机硬件相关,这里仅用 Intel 的 CPU 做一些说明:对于所有为 Intel 和 AMD x86-64 提供的优化选项都是用 m 开头的,下面写一些常用的选项:

-march

该选项用来指定 CPU 的类型,常用的有 i386 \ i486 \ i586 \ pentium-mmx \ i686 \ pentium2 \ pentium3 \ pentium-m \ pentium4 \ prescott \ k6 \ athlon \ athlon-4 \ k8 等等,读者可以根据自己的情况进行指定。

-mfpmath

该选项用于指定浮点运算单元的类型。包括

387

使用标准的数学协处理器

sse

使用 SSE 指令集提供的标量浮点运算。在 Pentium3 \ Athlon- 4 以及更新的芯片上支持这个特性。另外,在 pentium4 以及 AMD x86-64 处理器上,SSE2 还可以进行双精度浮点计算。

sse,387 混合使用 387 数学协处理器和 SSE 指令集,该选项可以充分的利用 CPU 的浮点寄存器和 xmm 寄存器,但是该选项还处在试验阶段。

-malign-double

该选项使得 GCC 把 double \ long double \ long long 类型的变量在 4 字节或 2 字节地址上对齐,在 Pentium 级的 CPU 上,这会使得代码的执行速度更快,当然带来的代价是需要更多的内存来执行程序。-mmmx –msse –msse2 –msse3 –m3dnow 这些选项用来启动内置函数直接使用这些处理器扩展指令的功能。在编译 3D 或多媒体程序的时候,使用他们是非常有效的。

3. 对调试的支持当程序出错的时候,我们可以在 Visual Studio 中轻松的进行调试,而在 Linux 中,一旦出现 Segmentation Fault,似乎我们除了用眼睛去看代码就没有更好的选择了,其实情况不然,用 GCC 向程序加入一些适当的调试信息,我们可以利用 GDB 去调试程序。在这里,我们介绍最为常用的 - g 和 -ggdb 选项。

先来看 -g。该选项可以利用操作系统的“原生格式(native format)”生成调试信息。GDB 可以直接利用这个信息。尽管我们可以把 - O 和 - g 放在一起使用,但是,这种做法是极为不推荐的。

如果你想用 GDB 来调试程序,那么你可以使用 -ggdb 来让 GCC 为 GDB 生成更为丰富的调试信息,但是,此时你就不能用其他的调试器来进行调试了。

最后要说明的是,上面这两个选项都可以接受一个输出调试信息的级别,默认的级别是 2。如果你指定 1 级(-g1),那么 GCC 会生成最少的调试信息,这包括函数和全局变量的描述信息,但是对于局部变量和行号等信息,在这个级别是不会输出的。另外一个级别是 3 级(-g3),在这一级别上,GCC 会为程序中的所有宏定义和符号生成调试信息。

看完上述内容,你们对 linux 程序开发如何入门有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注丸趣 TV 行业资讯频道,感谢大家的支持。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-04发表,共计7862字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)