Alan Luo 2017-01-13
本文目的是针对将熟悉C/C++语法,如何在Linux下进行的C/C++开发的入门指南。Linux下的开发和在Windows下的开发类似,主要区别点在于操作系统不同,开发工具,开发API,编译调试方法不一样,故主要将针对这些不同点进行阐述,使在Windows开发的程序员能够入门Linux下C++ 开发的行列中。
首先,你得有一台Linux机器,目前的开发环境是10.88.115.114,机器需要安装g++/gcc编译器环境,文本编辑器,如vim等,一般安装操作系统会安装好,如果系统没有需要自行安装。
输入g++ -v 查看本机是否安装g++环境
安装方式有两种,YUM安装和源代码安装方式。推荐使用YUM安装方式。
Yum安装可以自动解决库依赖问题,所以推荐使用。YUM安装g++:
yum list gcc-c++
yum install gcc-c++.i686
自动安装即可。
另外开发过程中,需要调试,故Linux机器也需要安装gdb调试工具。
Gdb安装方式类似:
yum install gdb
Linux下的开发一般不是直接在Linux下进行开发,当然如何愿意也是可以的,可以直接使用VIM进行开发。但是需要很长的时间熟练使用VIM的快捷键,对于入门开发来说过于困难,故直接在Windows下开发者居多。在Windows下开发Linux下应用主要使用的工具如下:
(1)Xshell,用于连接Linux主机,可以使用free for school版本,百度一下安装即可
最后可以配置成如下简洁界面,让人感觉轻松大气。
Alt+Ctrl+F组合键可以弹出文件传输界面,开发和升级的时候,在Linux和Windows之间进行文件传输。如图所示。
(2)Code::Blocks
在Windows下将源代码从linux下拉来后,需要在本地进行开发。可以直接使用文本编辑器开发,但是缺少关键字高亮,函数跳转等功能,开发起来比较困难。故需要使用到IDE工具。下面介绍3款工具。
第一款,Code::Blocks,这一款比较推荐,在Windows和Linux下都有版本。新建工程,File->New->Project,将代码加入工程后即可进行开发,可以关键字高亮,函数跳转,函数引用列表等功能。主要缺点是开发好的代码需要上传到Linux开发机器上进行编译调试。
第二款,Source Insight
Source Insight使用较广,使用方式和Code::Blocks基本一致,只是快捷键不一致。缺点同样是需要把文件上传后编译开发。
第三款,Eclipse+RSE插件
Eclipse安装Remote System Explorer插件后,可以直接连上linux的机器,对机器上的代码进行直接编辑开发,此种开发的模式优点是不需要对代码文件上传,缺点是对函数跳转,查找等功能很欠缺,基本上相当于文件编辑模式。
上面三种IDE都可以进行Linux下C++的开发,但是编译链接调试依然是在Linux环境下进行。所以可以根据各自的优缺点进行选择。
Linux下开发的基本技能要求如下:
熟悉Linux下基本命令:
cp /rm/ find/cd/ll/mkdir 等等
熟悉Makefile文件编写
开源库搜索与安装yum
调试工具gdb的使用
Linux API
下面将详细讲解这些技术的使用。
至此,Linux下环境的开发工具齐全了,下面开始从头开始搭建工程。
登录开发机器115.114,新建目录Demo,进入该目录:
cd /home/
mkdir Demo
cd Demo
新建3个文件
分别输入如下内容
1. print.h
#include
void printHello();
2. print.c
#include"print.h"
void printHello(){
printf("Hello, world\n");
}
3. main.c
#include "print.h"
int main(void){
printHello();
return 0;
}
helloworld:main.o print.o
g++ -o helloworld main.o print.o
main.o:main.cprint.h
g++ -c main.c
print.o:print.cprint.h
g++ -c print.c
clean: rmhelloworld main.o print.o
其中makefile的撰写是基于规则的,当然这个规则也是很简单的,就是:
target (生成的对象): prerequisites(生成对象的依赖条件)
command //任意的shell 命令
如helloworld:main.o print.o
g++ -o helloworld main.o print.o
需要生成可执行文件helloworld,则需要依赖main.o print.o 文件,即使用g++ -o helloword main.o print.o生成helloword,
其中-o 生成的可执行文件名称,main.o print.o是已经生成好的两个文件对象。
接下来,
main.o:main.cprint.h
g++ -c main.c
即main.o的生成由main.c和 print.h编译得来,即执行g++ -c main.c命令生成。以此类推。当然如果在项目源文件和头文件都比较多的情况下,采用该种编写方式会比较繁琐且容易出错,故可以使用Makefile中的一些函数进行自动编译。可参考Makefile的相关教程。
其中clean的命令是删除文件helloworld main.o print.o,写好此文件后,make clean 可以实现将生成的文件删除从而可以再次进行编译。
发好了源文件以及MakeFile文件后,接下来可以进行编译运行。在当前目录先执行make命令;
可以看到Makefile中的命令都已经执行,查看当前目录ls;
可以看到生成了可执行文件helloworld和中间过程文件main.o,print.o。
输入命令./helloworld后可以看到界面打印出了hello world字样。
程序开发必定需要进行调试开发。在Linux下开发调试主要依靠GDB工具。
首先,编译的时候需要在编译命令中加入-g选项,这样保证调试的时候可以打印出源代码。
添加-g,修改Makefile文件之后,重新编译make ,可以看到编译命令中多出了-g。
进入调试模式,gdb helloworld
gdb的命令很多,gdb把之分成许多个种类。help命令只是例出gdb的命令种类,如果要看种类中的命令,可以使用help
l+函数名称可以查看函数源码
设置断点,输入命令
b 3
则再文件main的第三行设置了断点。
如果需要设置其他文件中的函数断点,可以如图设置,即文件名加函数名称,或者函数行数即可
Info break 命令即可查看当前设置的所有断点。
输入命令r,调试运行程序开始。程序卡在第一个断点的位置上。此时输入命令 s,即可进入该函数里面进行调试,输入命令l即可查看当前函数的源代码;
输入命令n可以进行单步执行;
输入 p+变量名 可以打印当前变量的值;
输入命令q退出调试;
Gdb 命令丰富多彩,目前介绍的只是最基本的命令,但是针对一般的调试已经足够,需要用户自己不断的学习发掘才能最大限度的使用gdb的好处。
接下来介绍一个进阶版开发教程。主要从头开始搭建一个包含一些功能模块的项目。本Demo主要包括日志打印,配置文件读取,UDP端口监听,开启线程等功能。
mkdir HighDemo
然后创建cpp,.h文件
其中base64主要用来进行base64编码解码,comm_codec主要用来通用的解析XML,格式转换等函数集合,config主要用来加载配置文件config.xml,LogClinet主要用来打印日志文件,strtok_r主要用来字符串切割,其中NetFrame是包含main方法的主线程文件。创建完了CPP和头文件之后,将创建Makefile文件。
进阶版的Makefile,先从两个函数可以讲起。函数Wildcard和函数patsubst。
“$(wildcard *.cpp)”来获取工作目录下的所有的.cpp文件列表
以使用“$(patsubst %.cpp,%.o,$(wildcard *.cpp))”,首先使用“wildcard”函数获取工作目录下的.cpp文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。
三个变量分别是$@,$^,$<代表的意义分别是:
$@--目标文件,
$^--所有的依赖文件,
$<--第一个依赖文件。
所以本项目的Makefile文件写成如下
TARGET=NetFrame
CC=g++
INCLUDES+=-I./include -I/usr/local/src/oracle/10g/rdbms/public-I/usr/include/libxml2 -I/usr/local/ssl/include -I/usr/local/include
LIB=-lstdc++-lpthread -lrt -L/usr/local/src/oracle/10g/lib -lclntsh -L/usr/lib64 -lxml2-L/usr/local/ssl/lib -lcrypto
OBJS:=$(patsubst %.cpp,%.o,$(wildcard *.cpp))
$(TARGET):${OBJS}
$(CC) $^ $(LIB) -o $@
.cpp.o:
$(CC) $(FLAGS) $(INCLUDES) -o $@ -c $<
clean:
rm-rf $(TARGET)
rm-f $(OBJS)
输入命令
make
则生成可执行文件NetFrame
INCLUDES和LIB主要是使用到的库头文件和动态库或者静态库文件的路径,包含进来即可。如果使用了新的开源库,则需要安装以及查找对应的库路径添加进来。
如需要使用libcurl库,则yum search curl
找到curl-devel.x86_64,再yum install curl-devel.x86_64 安装即可
之后如果你不确定动态库被安装到哪里去了,可以输入如下命令:
find / -name libcurl*,如图
编写NetFrame.cpp文件。
首先导入相关头文件,其中<>表示引用的是编译器的类库路径里面的头文件" "引用的是你程序目录的相对路径中的头文件,设置一下常量(最好放在头文件里)。
之后定义Main函数,调用各个模块的函数接口实现对应的功能,如调用日志函数打印日志,调用配置文件解析配置,获取配置文件中的参数功能。
另外开启一条线程,进行UDP的监听操作,开启的端口和IP从配置文件中读取。
该线程实现的功能也很简单,用户发送指定格式的UDP包,系统收到报文后,解析报文内容进行返回数据或者重新加载配置文件等等。
输入命令./NerFrame命令启动进程。
另开一个窗口,输入测试数据
echo "task=reload&msg=pleasereload"|nc -u 127.0.0.1 9999
可以看到返回了msg里面的内容
服务端重新加载了配置文件。
至此,高阶版Linux下C/C++开发指南介绍完毕,从头开始实践可以把一个熟悉C/C++语法的程序员带入Linux的世界中。
另外,由于是在Linux下开发,所以需要熟悉Linux的系统函数,这些系统函数是在程序中大量使用到,如open,close,recvfrom等等,推荐一本书《UNIX操作系统设计》,可以学习很多操作系统的API,对于程序开发有很大的帮助。另外如果对Linux内核有兴趣的可以学习《深入理解Linux内核》