Linux编程环境
Linux环境下的编辑器
在Linux环境下有很多编译器,例如基于行的编辑器ed和ex, 基于文本的编辑器Vim、 Emacs等。使用文本编辑器可以帮助用户翻页、移动光标、查找字符、替换字符、删除等操作。本节中对Vim编辑器进行详细的介绍,并简单介绍其他的编辑器。
Vim使用简介
Vi 是UNIX系统下最通用的文本编辑器。Vi不是一 个所见即所得的编辑器,如果要进行复制和格式化文本需要手动输入命令进行操作。安装好Linux操作系统后, 一 般已经默认安装了Vi编辑器。为了使用方便,建议安装 Vi的扩展版本Vim, 它比Vi更强大,更加适合初学者使用。
1.Vim的安装
apt-get install vim
在Ubuntu下,apt-get工具对系统的软件包进行管理。install选项安装会自动查找和安装指定的软件包,其命令如下:
apt-get install 软件包名称
2.Vim编辑器的模式
-
Vim主要分为普通模式和插入模式。普通模式是命令模式,插入模式是编辑模式。
-
在插入模式下可以进行字符的输入,输入的键值显示在编辑框中,这些文本可以用于编辑。普通界面是进行命令操作的,输入的值代表一个命令。例如在普通模式下按h键,光标会向左移动一个字符的位置。
-
插入模式和普通模式的切换分别为按i键和Esc键。在普通模式下按i键,会转入插入模式;在插入模式下按Esc键进入普通模式。在用户进入Vim还没有进行其他操作时,操作模式是普通模式。
使用Vim建立文件
Vim的命令行格式为"vim文件名",文件名是所要编辑的文件名,例如要编辑一个"hello.c”的C文件,按照如下所述的步骤进行操作:
-
建立文件:
vim helloc.c
-
进入插入模式:打开文件后,默认是普通模式,按i键,进行插入模式。注:要回到普通模式只需按Esc键,有时按两次Esc键,Vim发车“嘀”一声,就表示Vim在普通模式下了。
-
文本输入:
#include <stdio.h> int main(void){printf("Hello World!\n"); return 0;}
-
退出Vim:编译完成后,按Esc键退出插入模式回到普通模式,输入":wq"退出Vim编辑器。
-
使用
ls -l
查看创建当前目录下的文件
使用Vim编辑文本
Vim的编辑命令有很多,如在Vim下移动光标,进行删除字符、复制、查找、转跳等操作。
1.移动光标 h、j、k、l
2.刪除字符x、dd、u、Ctrl+R
-
x:要删除一个字符可以使用x,普通模式下,将光标移动到需要删除的字符上面然后按x键。
-
dd:要删除一整行可以使用dd。
-
u:恢复删除可以使用u。
-
Ctrl+r:取消一个命令,可以将之前撤销的字符重新找回。
3.复制粘贴p、y
-
p:粘贴命令,将内存中的字符复制到当前光标的后面。使用前提是内存中有合适的字符串复制。例如:要将一行复制到某个地方,可以使用dd命令删除它,然后使用u命令恢复,这时内存中是dd命令删除的字符串。将光标移动到需要插入的行之前,使用p命令可用把内存中的字符串复制后放置在选定的位置。
-
y:复制命令,将指定的字符串复制到内存中,yw命令用于复制单纯,可用指定复制的单词数量,y2w复制两个单词。例如:
#include <stdio.h>
光标位于此行的头部,当输入y2w时字符串#include就复制到内存中,按p键后,如下:##include include <stdio.h>
-
注:命令y在进行字符串复制的时候包含末尾的空格。按行进行字符串的复制时,使用dd命令复制的方式比较麻烦,可以使用yy命令进行复制。
4.查找字符串"/"
查找字符串的命令是**“/xxx”**,其中xxx代表查找的字符串。例如:查找当前文件的printf字符串,可以输入下面命令:
:/printf
找到匹配字符串,光标在第一个合适的字符串光标上。查找其他匹配的字符串可以输入"n"向下移动到一个匹配的字符串上,输入字符“N”则会向上移动一个匹配的字符串上。
5.调到某一行 g
命令":n"可以让光标跳到某一行,其中n表示跳到的行数。另一种方式:命令nG,n为跳转的行数,5G是跳转到第5行命令,G大写。
Vim的格式设置
Vim设置缩进,设置Tab键对应空格的长度,设置行号等。
1.设置缩进
set cindent shiftwidth=n
2.设置Tab键的空格数量
set tabstop = n
3.设置行号
set number
注:Vim会根据**~/.vimrc文件设置vi的设置,可以修改文件.vimrc**来定制Vim。
Linux下的GCC环境编辑器
GCC是Linu下的编辑工具集,不仅可以编译C/C++语言,其他例如Objective-C、Pascal、Fortran、Java、Ada等语言。
GCC的C编译器是gcc,其命令如下:
GCC支持默认扩展名策略,下表是GCC默认文件扩展名的含义:
GCC下有很多编辑器,可以支持C语言、C++语言等多种语言,下表是常用的:
进行程序编译的时候,头文件路径和库文件是编译器默认查找的地方:
单个文件编译执行文件
使用gcc命令后面加上编译的C语言的源文件,GCC自动生成文件名为a.out的可执行文件。
/*hello.x*/
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
retrun 0;
}
编译成可执行文件:
gcc hello.c
首先将C文件编译成目标文件,然后将目标文件链接成可执行文件,最后删除目标文件。上述没有生成执行文件的名称,GCC将生成默认的文件名a.out。运行结果如下:
./a.out //执行a.out可执行文件
hello World!
生成指定可执行文件名,用-o,如下面生成test文件名:
gcc -o test hello.c
运行可执行文件:
./test
Hello World!
注:直接生成可执行文件的编译方法,中间文件作为临时文件操存在,在可执行文件生成后,会删除中间文件。
编译生成目标文件
GCC的**-c选项用于生成目标文件,生成的目标文件和源文件名称一样,只是扩展名为.o**。例:下面生成hello.o文件
gcc -c hello.c
生成指定文件名,使用-o,例如:将源文件hello.c编译目标文件,文件名为test.o:
gcc -c -o test.o hello.c
可以使用一条命令编译多个源文件,生成目标文件,例:一个项目包含file1.c、file2.c和file.c,生成三个目标文件:file1.o、file2.o和file3.o:
gcc -c file1.c file2.c file3.c
多文件编译
GCC可以自动编译链接多个文件,不管是目标文件还是源文件,都可以使用同一个命令编译到一个可执行文件中。例如:一个项目包含两个文件,文件string.c中有一个函数StrLen用于计算字符串长度,mian.c中调用这个邯郸将计算的结果显示出来。
①.源文件string.c
#define ENDSTRING '\0'
int StrLen(char *string)
{
int len =0;
while(*string++ !=ENDSTRING)
len++;
retrun len;
}
②源文件 main.c
# include <stdio.h>
extern int StrLen(char* str);
int main(void)
{
char src[] = "Hello Dymatic";
pritnf("string length is:%d\n",StrLen(src));
return 0;
}
③.编译运行
下面将两个源文件中的程序编译成一个执行文件,文件名为:test
gcc -o test string.c main.c
运行:
./test
string length is :13
另一种方法:将源文件编成目标文件,然后进行链接。例:下面将string.c和main.c源文件编译成目标文件string.o和main.o,然后将string.o和main.o链接生成test:
gcc -c string.c main.c
gcc -o test string.o main.o
预处理
C语言程序中,通常需要包含头文件并会定义一些宏,预处理过程将源文件中的头文件包进源文件中,并且将文件中定义的宏进行扩展。
编译程序时选项**-E**,进行预编译操作。例如如下文件string.c的预处理结果显示在计算机屏幕上:
gcc -E string.c
如果需要指定源文件预编译后生成的中间结果文件名,需要使用**-o**,下面将string.c进行预编译,生成string.i。string内容如下:
这时宏ENDSTRING,已经被替换称"\0"。
编译成汇编语言
生成汇编语言GCC选项是**-S**,默认情况下生成的文件名和源文件一致,扩展名为**.s**。
例:将C语言源文件string.c编译成汇编语言,文件名为string.s
gcc -S string.c
生成使用静态链接库
静态库是obj文件的一个集合,通常静态库以".a"为后缀,静态库由程序ar生存。
-
静态库的优点是可以在不用重新编译程序库代码的情况下,进行程序的重新链接,这种方法节省了编译过程的时间(在编译大型程序的时候,需要花费很长时间)。但是由于现在系统的强大,编译的时间已经不是问题。
-
静态库的另一个优势是开发者可以提供库文件给使用的人员,不用开放源代码,这是库函数提供者经常采用的手段。
-
当然这也是程序模块化开发的 一 种手段,使每个软件开发人员的精力集中在自己的部分。在理论上,静态库的执行速度比共享库和动态库要快 (1% ~5% )。
①.生成静态链接库
- 生成静态库,或者将一个obj文件加到已经存下的静态库的命令为"ar库文件obj文件1 obj文件2"。
- 创建静态库的最基本步骤是生成目标文件。
- 然后使用工具ar对目标文件进行归档。
- 工具ar的-r选项,可以创建库,并把目标文件插入到指定库中。
例如:将string.o打包为库文件libstr.a的命令为:
ar -rcs libstr.a string.o
②.使用静态链接库
在编译程序的时候经常需要使用函数库,例如经常使用的C标准库等。GCC链接时使用库函数和 一 般的obj 文件的形式是一 致的,例如对 main.c 进行链接的时候,需要使用之前已经编译好的静态链接库 libstr.a, 命令格式如下:
gcc -o test main.c libstr.a
也可以使用命令"-l库名"进行,库名是不包含函数库和扩展名的字符串。例如:编译main.c链接静态库libstr.a的命令可用修改为:
gcc -o test main.c -lstr
上面的命令将系统默认的路径下查找str函数库,并把它链接到要生成的目标程序上。可能系统提示无法找到库文件str,这是由于str库函数没有在系统默认的查找路径下,需要显示指定库函数的路径,例如库文件和当前编译文件在同一目录下:
gcc -o test main.c -L./ -lstr
注:在使用**-l选项时,-o选项的目的名称要在-l链接的库名称之前,否则gcc会认为-l**是生成目标而出错。
生成动态链接库
-
动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序。
-
动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的。库中函数和变量的地址是相对地址,不是绝对地址,其真实地址在调用动态库的程序加载时形成。
-
动态链接库的名称有别名(soname)、真名(realname)和链接名(linkername)。
-
别名由一 个前缀lib, 然后是库的名字,再加上一 个后缀".so"构成。真名是动态链接库的真实名称,一 般总是在别名的基础上加上一 个小版本号、发布版本等构成。
-
除此之外,还有一个链接名,即程序链接时使用的库的名字。在动态链接库安装的时候,总是复制库文件到某个目录下,然后用一 个软链接生成别名,在库文件进行更新的时候,仅仅更新软链接即可。
①.生成动态链接库
生成动态链接库,使用-fPIC选项或者-fpic选项。-fPIC和-fpic选项的作用是使得gcc生成的代码是位置无关的,例如下面得命令将string.c编译生成动态链接库:
gcc -shared -Wl,-soname,libstr.so -o libstr.so.l string.c
选项**“-soname,libstr.so"表示生成动态库的别名是libstr.so:”-o libstr.so.l"选项则表示是生成名字为libstr.so.l的实际动态链接库;-shared**表示格式编译器生成一个动态链接库。
生存动态链接库,一般复制到系统默认的动态链接库的搜索路径,通常有**/llib、/usr/lib、/usr/local/lib**,放在如何目录下都可以。
②.动态链接库的配置
动态链接库不能随便使用,要在运行的程序中使用动态链接库,需要指定系统的动态链接库搜索路径,让系统找到运行所需的动态链接库才可以,系统中的配置文件**/etc/ld.so.conf**是动态链接库的搜索路径配置文件。
在这个文件中,存放着可被Linux共享的动态链接库所在目录的名字(系统目录**/lib、/usr/lib**除外),多个目录名间以空白字符(空格、换行等)或冒号或逗号分隔。查看系统中的动态链接库配置文件的内容:
cat /etc/ld.so.conf
Ubunutu的配置文件将目录/etc/ld.so.conf.d中的配置文件包含进来,对这个目录下的文件进行查看:
ls /etc/ld.so.conf.d/
③.动态链接库管理命令
运行动态链接库的管理命令:ldconfig,ldconfig命令的作用是在系统的默认搜索路径,和动态链接库配置文件中所列出的目录里搜索动态链接库,创建动态链接库装入程序重要的链接和缓存文件。搜索完毕后,将结果写入缓存文件**/etc/ld.so.cache**中。ldconfig命令使用用法如下:
例:
ldconfig -p
:查看缓存文件中的动态链接库表。
ldconfig -v:将ldconfig在运行过程扫描的目录和共享库信息输出:
查看指定要扫描的目录,并将动态链接库放入系统中进行共享:
ldconfig 目录名
例:将扫描当前用户的lib目录,将动态链接库加入系统:
ldconfig ~/lib
注:如果在运行上述命令后,再次运行ldconfig而没有加参数,系统会将**/lib、/usr/lib及/etc/ld.so.conf**中指定目录中的动态链接库加入缓存,这时候上述代码中的动态链接可能不被系统共享了。
④.使用动态链接库
使用动态库:使用"-l库名",例如:将源文件main.c编译成可执行文件test,并链接库文件libstr.a或者libstr.so:
gcc -o tetst main.c -L./ -lstr
-L指定链接动态链接库的路径,-lstr链接库函数str。但运行test一般会出现而下问题:
由程序运行时没有找到动态链接库造成的,程序编译时链接动态链接库和运行时使用动态链接库的概念不同,在运行时,程序链接的动态链接库需要在系统目录下才行。解决方法:
-
将动态链接库的目录放哪程序搜索路径中,可以将库的路径加到环境变量LD_LIBRARY_PATH中实现,例:
将存放库文件libstr.so的路径**/example/ex02**加入到搜索路径中,再运行程序就没有之前的警告了。 -
第二种方法使用ld-Linux.so.2来加载程序:
加载test程序的命令:
注:如果系统到搜索路径下同时存在静态链接库和动态链接库,默认情况下会链接动态链接库。如果需要强制链接静态链接库,需要加上"-static"选项,上述编译方法改为如下:
动态加载库
动态加载库和一般的动态链接库所不同的是,一般动态链接库在程序启动的时候就要寻找动态库,找到库函数,而动态加载库用程序的方法来控制什么时候加载。动态加载库主要函数dlopen()、dlerror()、dlsym()和dlclose()。
①.打开动态库dlopen()函数