52、Linux编程标准与实践指南

Linux编程标准与实践指南

1. CD应用程序开发与Qt使用

在开发CD应用程序时,我们可以借助Qt GUI库和KDE小部件来实现一个图形用户界面(GUI)前端。以下是相关代码示例:

== QMessageBox::Yes)
{
return 0;
}
}
}
delete dialog;
MainWindow *window = new MainWindow( “Cd App” );
window->resize( 600, 400 );
a.setMainWidget( window );
window->show();
return a.exec();
}

完成代码编写后,还需要编写一个 .pro 文件,将其传递给 qmake 。以下是 cdapp.pro 文件的示例内容:

TARGET = app
MOC_DIR = moc
OBJECTS_DIR = obj
INCLUDEPATH = /usr/include/kde /usr/include/mysql
QMAKE_LIBDIR_X11 += -/usr/lib  
QMAKE_LIBDIR_X11 += /usr/lib/mysql
QMAKE_LIBS_X11 += -lkdeui -lkdecore -lmysqlclient
SOURCES = MainWindow.cpp main.cpp app_mysql.cpp AddCdDialog.cpp LogonDialog.cpp
HEADERS = MainWindow.h app_mysql.h AddCdDialog.h LogonDialog.h

这里可以将 app_mysql.c 重命名为 app_mysql.cpp ,将其视为普通的C++源文件,避免了将C目标文件链接到C++时的小麻烦。接下来,执行以下命令进行编译和运行:

$ qmake cdapp.pro –o Makefile
$ make
$ ./app

如果一切顺利,你将拥有一个可用的CD数据库应用程序。你还可以尝试实现MySQL接口中的其他功能,如向CD添加曲目或删除CD,以更深入地了解KDE/Qt。这需要创建对话框、新的菜单项和工具栏项,并编写底层逻辑。

2. Linux标准概述

Linux最初只是一个内核,为了使其成为一个有用的系统,需要添加来自GNU项目的工具,这些工具是当时UNIX和类UNIX系统上常见程序的克隆。不同的UNIX(后来的Linux)供应商为其提供的命令和实用程序添加了专有扩展,文件系统布局也略有不同,这使得创建可在多个系统上运行的应用程序变得困难。因此,需要进行标准化以防止UNIX系统碎片化。

随着时间的推移,不仅这些标准在不断发展,Linux本身也在社区的推动下以惊人的速度得到增强,许多商业组织如Red Hat和Canonical,甚至非Linux供应商如IBM都提供了支持。Linux及其相关工具和实用程序越来越受欢迎,UNIX供应商也开始对其UNIX产品进行更改,以使其与Linux更兼容。

下面将重点介绍几个关键标准:
- C编程语言标准 :C语言是Linux编程的事实上的标准语言,了解其起源、发展以及如何确保程序符合标准对于编写可移植的C程序至关重要。
- UNIX标准 :特别是IEEE开发的POSIX标准和The Open Group开发的The Single UNIX Specification。
- Linux Standard Base(LSB) :由Free Standards Group制定,定义了标准的Linux文件系统布局。

3. C编程语言标准
3.1 C语言的历史

C编程语言起源于20世纪70年代左右,部分基于早期的编程语言BCPL和B语言的扩展。1974年,Dennis M. Ritchie编写了该语言的参考手册,同年C语言被用于在PDP - 11上重写UNIX内核。1978年,Brian W. Kernighan和Ritchie编写了经典的《The C Programming Language》。

随着时间的推移,C语言的语法不断发展,但与原书描述的语言差异越来越大,因此需要一个更精确且与当前用法一致的标准。1983年,ANSI成立了X3J11标准委员会来开发该语言的清晰简洁定义。1989年,该标准作为ANSI标准《Programming Language C》(X3.159 - 1989)发布,简称C89或C90,后来成为ISO标准ISO/IEC 9899:1990。

1993年,委员会开始致力于下一版本的标准,即C9X。1999年,新的标准正式成为C99标准(ISO/IEC 9899:1999)。目前仍有一个工作委员会J11负责C语言及其库的标准化工作,你可以在http://j11.incits.org/ 了解更多关于C语言当前标准工作的详细信息。

3.2 GNU编译器集合(GCC)

GNU项目在开发了Emacs编辑器后,于1987年发布了第一个官方版本的完全免费的C编译器gcc。最初,gcc是GNU C编译器,但现在这个基本的编译器框架支持多种语言,如C++、Objective - C、FORTRAN、Java和Ada,以及这些语言的库,因此其定义已调整为更合适的GNU Compiler Collection。

gcc一直是Linux的标准编译器,C或C++是Linux上编写程序的主要语言。你可以在http://gcc.gnu.org/ 找到gcc的主页。GCC能够很好地跟踪不断发展的C标准,但也允许一些扩展,并且与几乎所有编译器一样,在标准发布和完全实现该规范的编译器之间不可避免地会有轻微延迟。有时,gcc会提前预测标准的微小变化,这可能会让人感到困惑。

3.3 GCC选项

为了确保编写的C代码符合语言标准,gcc提供了多种选项,主要分为以下三类:
- 控制标准版本的选项
- -ansi :这是最重要的标准选项,告诉编译器遵循ISO C90标准。它会关闭某些与标准不兼容的gcc扩展,禁用C++( // )风格的注释,并启用ANSI三元组功能。同时,它会定义宏 __STRICT_ANSI__ ,关闭头文件中与标准不兼容的一些gcc扩展。
- -std= :该选项允许通过提供参数来更精细地控制使用的标准,主要选项如下:
- c89 :支持C89标准。
- iso9899:1999 :支持最新的ISO C90标准。
- gnu89 :支持C89标准,但允许GNU扩展和一些C99特性。从gcc 4.2版本开始,这是默认行为。
- 控制头文件的定义选项
- __STRICT_ANSI__ :强制使用ISO标准C,当在编译行选项中给出 -ansi 时会定义该宏。
- _POSIX_C_SOURCE = 2 :启用由IEEE Std 1003.1和1003.2标准定义的特性。
- _BSD_SOURCE :启用BSD类型的特性。如果这些特性与POSIX定义冲突,BSD定义优先。
- _GNU_SOURCE :允许广泛的特性,包括GNU扩展。如果这些特性与POSIX定义冲突,POSIX定义优先。
- 警告选项
- -pedantic :这是检查干净C代码最强大的编译器选项。除了开启检查符合标准的C代码的选项外,它还会关闭一些标准不允许的传统C构造,并禁用所有对标准的GNU扩展。如果你希望C代码尽可能可移植,应使用此选项,但缺点是编译器对代码的清洁度要求非常高,有时需要仔细思考才能消除最后几个警告。
- -Wformat :检查 printf 系列函数的参数类型是否正确。
- -Wparentheses :检查是否总是提供括号,即使在某些不需要的情况下。这对于检查复杂结构的初始化是否符合预期非常有用。
- -Wswitch-default :检查所有 switch 语句是否都有默认情况,这通常是良好的编码实践。
- -Wunused :检查各种情况,如声明但未定义的静态函数、未使用的参数和丢弃的结果。
- -Wall :开启gcc的大多数警告,包括上述所有 -W 选项(不包括 -pedantic ),是保持代码清洁的好方法。

一般建议使用 -Wall 选项,它在检查代码质量和避免编译器产生过多琐碎警告之间取得了很好的平衡。

4. 接口和Linux Standard Base(LSB)
4.1 LSB概述

从原始C代码层面上升到操作系统提供的接口(系统函数)层面,标准化包括库提供的函数和底层操作系统提供的系统调用。这两个方面都有两个层次的细节,即哪些接口存在以及接口的定义。

Linux在这方面的权威文档是The Linux Standards Base(LSB),可在http://www.linuxbase.org 或http://www.linux-foundation.org/en/LSB 找到。该标准已经发布了多个版本,并且工作仍在进行中。你可以在http://www.linux-foundation.org/en/Products 查看通过认证的发行版列表,包括各种版本的Red Hat、SUSE和Ubuntu等,但要注意发行版发布后需要一段时间才能完成认证检查。

LSB(截至3.1版本)定义了三个合规领域:
- Core :主要库、实用程序和一些关键文件系统位置。
- C++ :C++库。
- Desktop :桌面安装的附加文件,主要是各种图形库。

这里主要关注Core部分的规范。

4.2 LSB标准库

LSB以两种方式定义必须存在的接口:
- 对于主要由GNU C库实现或倾向于Linux独有的标准的函数,LSB定义了接口及其行为。
- 对于其他接口,主要是由于Linux类UNIX特性而产生的接口,规范只是声明某个特定接口必须存在,并且其行为必须符合另一个标准,通常是Common Application Environment(CAE)或更常见的The Single UNIX Specification,可从The Open Group(http://www.opengroup.org/)获取,部分内容可在http://www.unix.org/online.html (目前需要注册)查看。

不幸的是,Linux的底层标准(UNIX标准)历史复杂,可供选择的标准过多,不过大多数标准版本之间是密切兼容的。

4.3 UNIX标准的历史

UNIX起源于20世纪60年代末的AT&T Bell Laboratories,Ken Thompson和Dennis Ritchie编写了一个最初仅供个人使用的操作系统,名为Unics,后来名称改为UNIX。AT&T允许大学获取其源代码进行研究,由于其简洁的设计和强大的概念,UNIX迅速变得非常流行。

BSD操作系统是加利福尼亚大学伯克利分校开发的一个变体,该校在网络方面进行了大量工作。20世纪80年代中期左右,AT&T开始将UNIX商业化,其最受欢迎的版本是UNIX System V。许多其他变体也相继出现,各公司为了增加价值添加了专有扩展。

后来,AT&T将其UNIX业务出售给Novell,1994年Novell决定退出UNIX业务,导致权利和商标的所有权变得混乱,并引发了各种法律诉讼。

1988年,IEEE发布了第一套标准:POSIX(IEEE 1003)标准,旨在为计算机环境提供一个明确的可移植接口规范。1994年,X/OPEN公司(一个中立的供应商组织)发布了更庞大的X/OPEN CAE(Common Applications Environment)规范,它是IEEE POSIX标准的超集,在许多方面与POSIX标准技术上相同。后来,X/OPEN公司与OSF合并成立了The Open Group,CAE标准在2002年更新并发布为The Single UNIX Specification,Version 3。LSB最常参考的就是这个规范。

4.4 使用LSB标准库

对于编写可移植的C(或C++)程序的开发者来说,需要注意以下两点:
- 首先,检查你使用的库函数是否在LSB规范中列出。如果没有,可能会遇到难以移植的问题,应寻找实现所需功能的标准方法。你可以尝试使用 apropos Linux命令在在线手册页中搜索相关参考。
- 其次,更困难的是检查你使用的函数行为是否是规范的一部分,而不是依赖未指定的行为。如果LSB未定义函数的使用方式,可能需要参考The Single UNIX Specification。在线Linux手册是检查未定义或可能错误行为的好地方,许多页面都有“BUGS”部分,提供了有关Linux中特定调用可能未完全实现标准或存在已知缺陷或行为异常的宝贵信息。

4.5 LSB用户和组

LSB关于用户和组的规范简洁易懂,主要内容如下:
- 永远不要直接读取 /etc/passwd 等文件,而应始终使用标准库调用(如 getpwent )或标准实用程序(如 passwd )来访问用户详细信息。
- 必须有一个名为 root 的用户位于 root 组中, root 是具有完全权限的管理用户。还有一些可选的用户和组名,标准应用程序不应使用,这些名称供发行版使用。
- 用户ID低于100的是系统账户,100 - 499由系统管理员和安装后脚本分配,500及以上是普通用户账户。

一般来说,大多数Linux程序员了解这些关于用户的标准就足够了。

4.6 LSB系统初始化

系统初始化一直是个令人烦恼的问题,因为不同发行版之间存在细微差异。Linux从类UNIX操作系统继承了运行级别(run levels)的概念,用于定义系统在任何时候运行的服务。以下是Linux中常见的运行级别定义:
| 运行级别 | 用途 |
| ---- | ---- |
| 0 | 停机。作为系统关闭时的逻辑状态。 |
| 1 | 单用户模式,除 / 之外的目录可能未挂载,网络功能未启用,通常用于系统维护。 |
| 2 | 多用户模式,但网络功能未启用。 |
| 3 | 正常的多用户模式,启用网络,使用文本模式登录屏幕。 |
| 4 | 保留。 |
| 5 | 正常的多用户模式,启用网络和图形登录屏幕。 |
| 6 | 伪级别,用于重启。 |

LSB列出了这些运行级别,但不要求必须使用,不过它们非常常见。与这些运行级别相关的是一组用于启动、停止和重启服务的初始化脚本。以前,这些脚本位于 /etc 下的不同位置,如 /etc/init.d /etc/rc.d/init.d ,这种差异常常导致混淆,因为更换发行版的用户可能找不到初始化脚本,安装程序也可能将脚本放置在错误的目录中。

5. 总结与实践建议

在Linux编程领域,遵循标准是编写可移植、稳定且易于维护代码的关键。从C语言标准到Linux标准库,再到LSB的各个方面,每一个标准都为我们的编程工作提供了指导和保障。

5.1 标准的重要性
  • 可移植性 :遵循C语言标准和LSB标准,能够确保我们的程序可以在不同的Linux发行版甚至其他类UNIX系统上运行。例如,使用符合ISO C标准的代码,在不同的gcc版本和不同的Linux系统中都能保持较好的兼容性。
  • 稳定性 :标准定义了函数和接口的行为,使得我们的代码在不同环境下的表现更加可预测。避免依赖未定义的行为或特定系统的扩展,能够减少因环境变化而导致的错误。
  • 维护性 :符合标准的代码更容易被其他开发者理解和维护。当团队协作开发或代码需要长期维护时,遵循标准可以提高代码的可读性和可维护性。
5.2 实践建议
  • 选择合适的标准 :根据项目的需求和目标,选择合适的C语言标准和LSB标准。如果项目需要兼容较旧的系统,可以选择C89标准;如果需要使用新的特性,可以考虑C99标准。同时,确保使用的库函数和接口符合LSB规范。
  • 使用GCC选项 :合理使用gcc的选项来确保代码符合标准。建议在开发过程中使用 -Wall 选项,开启大多数警告,帮助发现潜在的问题。对于对代码质量要求较高的项目,可以考虑使用 -pedantic 选项,进行更严格的检查。
  • 参考标准文档 :在编写代码时,及时参考相关的标准文档,如C语言标准文档、The Single UNIX Specification等。同时,利用在线Linux手册中的“BUGS”部分,了解函数的潜在问题。
  • 测试与验证 :在不同的环境中对代码进行测试,确保其在各种情况下都能正常工作。可以使用虚拟机或容器来模拟不同的Linux发行版和系统配置。
6. 拓展实践:实现CD应用程序的更多功能

在前面介绍了CD应用程序的基本开发和相关标准后,我们可以进一步拓展该应用程序的功能,以更深入地了解KDE/Qt和Linux编程。

6.1 功能规划

以下是一些可以实现的功能:
- 添加曲目到CD :允许用户为已有的CD添加曲目信息。
- 删除CD :提供删除指定CD记录的功能。
- 搜索功能 :实现根据CD名称、艺术家等信息搜索CD的功能。

6.2 实现步骤

以下是实现“添加曲目到CD”功能的大致步骤:

graph TD;
    A[创建添加曲目对话框] --> B[获取用户输入的曲目信息];
    B --> C[验证输入信息的有效性];
    C -->|有效| D[将曲目信息添加到对应的CD记录中];
    C -->|无效| E[提示用户重新输入];
    D --> F[更新数据库和界面显示];
  • 创建添加曲目对话框 :使用KDE/Qt的对话框类创建一个界面,让用户输入曲目名称、时长等信息。
  • 获取用户输入 :从对话框中获取用户输入的信息。
  • 验证输入信息 :检查输入的信息是否符合要求,如曲目名称不能为空等。
  • 添加曲目信息 :如果输入信息有效,将曲目信息添加到对应的CD记录中,并更新数据库。
  • 更新界面显示 :刷新CD列表或详细信息页面,显示更新后的内容。

以下是简单的示例代码,用于创建一个添加曲目对话框:

#include <QDialog>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>

class AddTrackDialog : public QDialog {
    Q_OBJECT
public:
    AddTrackDialog(QWidget *parent = nullptr) : QDialog(parent) {
        trackNameEdit = new QLineEdit(this);
        durationEdit = new QLineEdit(this);
        okButton = new QPushButton("OK", this);
        cancelButton = new QPushButton("Cancel", this);

        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(new QLabel("Track Name:", this));
        layout->addWidget(trackNameEdit);
        layout->addWidget(new QLabel("Duration:", this));
        layout->addWidget(durationEdit);
        layout->addWidget(okButton);
        layout->addWidget(cancelButton);

        setLayout(layout);

        connect(okButton, &QPushButton::clicked, this, &AddTrackDialog::accept);
        connect(cancelButton, &QPushButton::clicked, this, &AddTrackDialog::reject);
    }

    QString getTrackName() const {
        return trackNameEdit->text();
    }

    QString getDuration() const {
        return durationEdit->text();
    }

private:
    QLineEdit *trackNameEdit;
    QLineEdit *durationEdit;
    QPushButton *okButton;
    QPushButton *cancelButton;
};
7. 总结

通过本文的介绍,我们了解了Linux编程中的多个重要方面,包括CD应用程序的开发、C语言标准、GCC选项、LSB标准以及如何拓展应用程序的功能。在实际编程中,我们要始终牢记遵循标准的重要性,不断学习和实践,提高自己的编程能力。希望本文能为你在Linux编程的道路上提供有价值的参考和指导。

【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺和拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)内容概要:本文介绍了基于蒙特卡洛和拉格朗日方法的电动汽车充电站有序充电调度优化方案,重点在于采用分散式优化策略应对分时电价机制下的充电需求管理。通过构建数学模型,结合不确定性因素如用户充电行为和电网负荷波动,利用蒙特卡洛模拟生成大量场景,并运用拉格朗日松弛法对复杂问题进行分解求解,从而实现全局最优或近似最优的充电调度计划。该方法有效降低了电网峰值负荷压力,提升了充电站运营效率经济效益,同时兼顾用户充电便利性。 适合人群:具备一定电力系统、优化算法和Matlab编程基础的高校研究生、科研人员及从事智能电网、电动汽车相关领域的工程技术人员。 使用场景及目标:①应用于电动汽车充电站的日常运营管理,优化充电负荷分布;②服务于城市智能交通系统规划,提升电网交通系统的协同水平;③作为学术研究案例,用于验证分散式优化算法在复杂能源系统中的有效性。 阅读建议:建议读者结合Matlab代码实现部分,深入理解蒙特卡洛模拟拉格朗日松弛法的具体实施步骤,重点关注场景生成、约束处理迭代收敛过程,以便在实际项目中灵活应用改进。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值