软件项目在实际部署的时候,当客户环境要求linux系统时,不可避免的需要将windows版本移植到linux系统中。下面来介绍linux系统下软件开发的基础及所遇到的问题。
1.Linux环境简介
Linux版本号:num.num.num
其中第一个数字是主版本号,第二个数字是次版本号,第三个数字是修订版本号.如果次版本号是偶数,那么该内核就是稳定版的;若是奇数,则是开发版的.头两个数字合在一齐可以描述内核系列.如稳定版的2.6.4,它是2.6版内核系列。
1.2 Linux下应用软件
语言及编程环境:c、c++、java、python和fortan等。图形环境:gnome、kde、gimp、windowmaker和icewm等。编辑器:xemacs、vim、gedit和pico等。shells:bash、tcsh、ash和csh等。文字处理软件:openoffices、kword和abiword等。数据库:mysql、postgresql和oracle等。
1.3 7个知识点
是大小写敏感的系统;
文件名最多可以有256个字符;
文件名前面带”.”的文件在输入”ls”或者”dir” 命令时一般不显示。可以把这些文件看作是隐含文件,当然你也可以使用命令”ls –a”来显示这些文件;
目录操作符,请用“/”代替“\”;
在Linux系统下,所有的目录显示在单一目录树下;
在配置文件里,以#打头的行是注释行,总是在修改地方对应地加入一些关于修改的注释,你会发觉在以后的管理中获益多多;
和其他的多用户操作系统类似,在Linux下,文件和目录有自己的拥有者和访问权限。学习一些关于文件权限管理的相关知识,否则你肯定会觉得Linux实在很麻烦。
2.基于文本的C/C++
为什么选择文本编写程序?
在以命令行方式启动Linux,或者通过ssh 远程登陆到某Linux 系统时,很可能只有vi这样一个工具可以用来编写程序。(何为ssh:专为会话和其他网络服务提供安全性的协议。)
C/C++语言非常灵活,是众多专业程序员最为喜欢的编程语言之一。下面讨论基于文本的C/C++编程问题,主要涉及:如何编写程序,如何编译,如何调试,如何运行。涉及的开发工具有GNU C/C++、GNU GDB。
2.1 vi 最基本操作
vi用不同的颜色表示不同的程序元素,增加了程序的可读性,看起来也特别漂亮。好,下面结合一个简单的例子,来讨论vi的最基本操作。值得注意的是,vi支持的操作是非常丰富的,这里只介绍最常用的操作。执行下面的指令,在当前目录下建立一个文件名为calculator.c的程序文件。如果该文件已存在,此命令将打开这个文件。
vi calculator.c
图2-1
图2-2
执行完上面的指令后,就进入了vi编辑界面。下面说说vi最基本的操作方法。进入编辑界面后,按i键就进入了“插入”模式,按Esc 键就退出了“插入”模式。如此可以来回切换。 不管哪种模式,都可以用光标键(←↑↓→)及Home、End、PageUp、PageDn键移动光标。这与图形方式下的操作习惯是一致的。在“插入”模式下就可以输入字符了。可以用Delete 和BackSpace键删除字符。在非“插入”模式下可以执行一些带冒号的指令。例如:w存盘,注意是输入一个冒号后面再跟一个字母w。还有一些其他指令,列举如下: :wq 存盘并退出vi。 :q 退出vi。如果尚未保存,vi会提示,并拒绝退出。 :q! 不保存已做的修改,强制退出。
2.2 基于文本的C/C++
基本开发工具:
GNU C/C++(gcc/g++)、GNU GDB;
例:如果提示:bash: g++: command not foun,说明系统中没有安装g++,需要安装。
Centos下:yum install gcc gcc-c++
ubuntu下:apt-get install gcc gcc-c++
(安装软件的另一种方式:
rpm -ivh XXX.rpm 卸载:rpm -e packgename)
2.3 GNU gdb 调试
如果编译时,使用下面的指令(增加了参数-g),就会生成带源代码调试符号的可执行文件。编译形成的可执行文件有7KB。之所以增加了2KB,就是因为增加的调试符号。 gcc -o calc hello.c –g 或 g++ -o hw hello.cxx -g 进一步地,就可以执行下面的指令启动调试工具进入调试环境对程序进行调试了。 gdb calc 在调试环境下,可以输入下列指令来控制调试。 l 28 第一个字母是小写的L,列出第28行附近的源程序。 b sum 在sum函数处设断点 b 25 在第25行处设断点 r 运行程序 n 单步执行,不进入函数 s 单步执行,进入函数 c 继续连续执行 p choice 显示变量choice 的值 q 退出调试环境 k 杀死程序
如果提示:bash: gdb: command not foun,说明系统中没有安装gdb,需要安装。
图2-3
图2-4
3.集成开发环境的使用
QT是一个1991年由奇趣科技开发的跨平台应用程序开发框架。它既可以开发程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,易于扩展,允许组件编程。
3.1 建立工程
图3-1
图3-2
图3-3
3.2 动态链接库的创建
TEMPLATE改为lib
图3-4
4.常见问题
4.1 时间函数
主要的两个时间结构类型:
:长×××,保存从1970年1月1日0时0分0秒到现在时刻的秒数;
:struct tm:
{ int tm_sec; /* 秒 – 取值区间为[0,59] */ int tm_min; /* 分 - 取值区间为[0,59] */ int tm_hour; /* 时 - 取值区间为[0,23] */ int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */ int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */ int tm_year; /* 年份,其值等于实际年份减去1900 */ int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期天
int tm_yday; /* 从每年的1月1日开始的天数 – 取值区间为[0,365]
int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。
不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/ };
char *asctime( const struct tm *ptr );
功能:函数将ptr所指向的时间结构转换成下列字符串:
Mon Jun 26 12:03:53 2000
clock_t clock( void );
功能:函数返回自程序开始运行的处理器时间,如果无可用信息,返回-1。
转换返回值以秒记, 返回值除以CLOCKS_PER_SECOND.
double difftime( time_t time2, time_t time1 );
功能:函数返回时间参数time2和time1之差的秒数表示。
struct tm *localtime( const time_t *time );
功能:函数返回本地日历时间。
time_t mktime( struct tm *time );
功能:函数转换参数time 类型的本地时间至日历时间,并返回结果。
sleep()函数:
windows下:
#include <windows.h>
Sleep(1000),以毫秒为单位;
Linux下:
#include "unistd.h"
sleep(1), 以秒为单位
usleep(1000),以毫秒为单位
4.2 日志组件的使用
日志组件是一个成熟的基于C++的库,可以方便地引入程序中,实现关键代码处的日志记录。
以下为使用该日志组件时所需的基本文件。
图4-1
windows系统下,日志组件的使用非常方便,只需将相应的.dll,.lib,及log4cxx.properties放入相应工程,并导入即可。由于日志库本身依赖于hpr库,因此还需hpr.dll,hpr.lib文件。
图4-2
在linux系统下使用日志库,需要更加繁琐的步骤,与windows系统略有不同。步骤如下:
1、将相应.so共享库放入相应工程;
2、编译运行;
3、运行时会提示错误,找不到以下文件:libexpat.so.0
该文件一般存在于目录/usr/lib下,如果是虚拟机环境,一般为/usr/lib/vmware-tools/lib32。也可以使用命令方式来寻找该文件。Find -name 'libexpat.so.0',如果没有,则链接libexpat.so.1,即
sudo ln -s /lib/libexpat.so.1.5.2 /usr/lib/libexpat.so.0。找到该文件,直接放入工程中,即可运行程序。
4.3 其他
4.3.1 多线程同步
定义对象互斥锁:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
使用:
pthread_mutex_lock(&mutex);
g_trafficMap.clear();
pthread_mutex_unlock(&mutex);
4.3.2 Strace命令
strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。
strace -f -T -tt -o a.txt ./cale
./cale为执行程序命令,cale为程序名。
4.3.3 复杂容器
复杂容器的定义,例如:
在windows下vector<pair<int, int>>v;正确
但在linux下会出现以下错误:
图4-3
需要写成:vector<pair<int, int> >v,即“>>”中间
多加一个空格“> >”
4.3.4 动态库兼容问题
可能是引用的库可能跟当前操作系统位数不同的原因。
首先查看了当前系统下的位数 shell下输入: getconf LONG_BIT
得知系统为64位,再查询库文件编译时的系统位数,shell下输入:readelf -h libxxxx.so
返回CLASS一行显示ELF32,可知该库文件实在32位系统下编译的。
readelf -h也可以查看可执行程序。
/usr/include/gnu/stubs.h:7:27: error: gnu/stubs-32.h: No such file or directory make: *** [TrafficInfo.o] Error 1
是缺少需要的程序包解决办法:安装缺少的包
yum install glibc-devel
但是如果在x86_64平台下编译32bits应用,则还需要安装glibc-devel.i686,如下:
sudo yum -y install glibc-devel.i686
4.3.5 内存检测工具
内存检测:yum install valgrind
valgrind --tool=memcheck ./cale
图4-4
4.3.6 安装问题
在liunx系统安装一些rpm软件包时,经常会遇到如下错误,
warning: *****.rpm: Header V3 DSA signature: NOKEY, key ID e8562897 rpm Header V3 DSA signature: NOKEY, key ID rpm -ivh *****.rpm
warning: *****.rpm: Header V3 DSA signature: NOKEY, key ID e8562897
这是由于yum安装了旧版本的GPG keys造成的。
解决办法如下:
改为 rpm -ivh *****.rpm --force --nodeps