《Linux系统编程(第2版)》——第1章 入门和基本概念 1.1 系统编程

第1章 入门和基本概念

摆在你面前的是一本关于系统编程的书,你将在本书中学习到编写系统软件的相关技术和技巧。系统软件运行在系统的底层,与内核和系统核心库进行交互。常见的系统软件包括Shell、文本编辑器、编译器、调试器、核心工具(GNU Core Utilities)以及系统守护进程。此外,网络服务、Web服务和数据库也属于系统软件的范畴。这些程序都是基于内核和C库实现的,可以称为“纯”系统软件。相对地,其他软件(如高级GUI应用),很少和底层直接交互。有些程序员一直在编写系统软件,而有些程序员则只投入了很少一部分时间。不管怎样,深入理解系统编程都能让他受益匪浅,不管你是把系统编程作为制胜法宝,还是认为它仅仅作为高层次概念的基础,系统编程是编写所有软件的灵魂。

确切地说,这是一本关于Linux的系统编程的书。Linux是类UNIX的现代操作系统,由Linus Torvalds和全球松散的程序员社区从零开始实现。尽管Linux和UNIX有着共同的目标和理念,但Linux并不是UNIX。Linux遵循自己的原则,关注方方面面的需求,专注于实用功能的开发。总的来说,Linux系统编程的核心和任何其他UNIX系统并没有区别。然而,除了这些基本点,和传统的UNIX系统相比,Linux有其自身的特点Linux支持更多的系统调用,有不同的行为和新的特性。

1.1 系统编程

从传统角度而言,所有的UNIX编程都属于系统级编程的范畴。这是由于UNIX系统并没有提供很多高级抽象,甚至是在如X Windows这样的系统上开发应用,也会涉及大量的UNIX的核心API。因此,可以说本书是通用的Linux编程指南。然而,本书并不涉及Linux编程环境——比如,书中没有任何关于如何使用make的说明。本书涵盖的是现代Linux机器上所使用的系统编程API。

系统编程和应用编程存在一些区别,但也有很多共性。系统编程最突出的特点在于要求系统程序员必须对其工作的硬件和操作系统有深入全面的了解。系统程序主要是与内核和系统库打交道,而应用程序还需要与更高层次的库进行交互,这些库把硬件和操作系统的细节抽象封装起来。这种抽象有以下几种目的:一是增强系统的可移植性,二是便于实现不同系统版本间的兼容,三是可以构建更易于使用、功能更强大或二者兼而有之的高级工具箱。对于一个应用,使用多少系统库和高级库取决于应用的运行层次。即使是开发那些基本不用系统库的应用,也能够通过了解系统编程而受益匪浅。对底层系统的深入理解和良好实践,对任何形式的编程都大有裨益。

1.1.1 为什么要学习系统编程
最近10年,不管是Web开发(如JavaScript)还是托管代码(如Java),应用编程的趋势都是逐渐远离系统级编程向高级开发发展。然而,这种开发趋势并非意味着系统编程的终结。实际上,依然需要有人来开发JavaScript解释器和Java虚拟机,这本身就是系统编程。此外,Python、Ruby或Scala程序员还是可以从系统编程中受益的,因为深入了解计算机灵魂的程序员在任何层次都能够编写出更好的代码。

虽然应用编程的趋势是逐渐远离系统级编程,绝大部分的UNIX和Linux代码还是属于系统级编程范畴,其中大部分是用C和C++实现的,主要是C库和内核的接口。另外,传统的系统编程——如Apache、bash、cp、Emacs、init、gcc、gdb、glibc、ls、mv、vim和X,也都不会很快过时。

系统编程通常包含内核开发,至少包括设备驱动编程。但是,和多数系统编程的书籍一样,本书并不讨论内核开发,而是专注于用户空间的系统级编程——即内核之上的所有内容(尽管了解内核对于理解本书大有裨益)。设备驱动编程是个很宽泛博大的主题,已经有很多书籍对此做了专门而又深入的探讨。

什么是系统级应用接口?在Linux上如何编写系统级应用?内核和C库到底提供了什么?如何优化代码?Linux上编程有什么技巧?和其他的UNIX版本相比,Linux提供了哪些精巧的系统调用?这些系统调用是如何工作的?本书将对这些问题一一进行探讨。

1.1.2 系统编程的基础
Linux系统编程有3大基石:系统调用、C库和C编译器,每个都值得深入探讨。

1.1.3 系统调用
系统编程始于系统调用,也终于系统调用。系统调用(通常简称为syscall)是为了从操作系统请求一些服务或资源,是从用户空间如文本编辑器、游戏等向内核(系统的核心)发起的函数调用。系统调用范围很广,从大家都熟悉的如read()和write(),到罕见的如get_thread_area()和set_tid_address()都在其范畴之内。

Linux实现的系统调用远远少于其他内核。举例来说,微软的Windows,其系统调用号称有几千个,而Linux x86-64体系结构的系统调用大概只有300个。在Linux内核中,每种体系结构(Alpha、x86-64或PowerPC)各自实现了标准系统调用。因此,不同体系结构支持的系统调用可能存在区别。然而,超过90%的系统调用在所有的体系结构上都实现了。本书所探讨的正是这部分共有的内容。

调用系统调用
位于用户空间的应用程序无法直接访问内核空间。从安全和可靠性角度考虑,也需要禁止用户空间的应用程序直接执行内核代码或操纵内核数据。但从另外一个角度看,内核也必须提供这样一种机制,当用户空间的应用希望执行系统调用时,可以通过该机制通知内核。有了这种机制,应用程序就可以“深入”内核,执行内核允许的代码。这种机制在不同的体系结构上又各不相同。举个例子,在i386微处理器上,用户空间的应用需要执行参数值为0x80的软件中断指令int。该指令会把当前运行环境从用户空间切换成内核空间,即内核的保护区域,内核在该区域执行中断处理函数——中断0x80的处理函数是什么呢?只能是系统调用处理函数!

应用程序通过寄存器告诉内核调用哪个系统调用以及传递什么参数。系统调用以数值表示,从0开始。举个例子,在i386微处理器体系结构上,要请求系统调用5(即open()),用户空间在发送int指令前,需要把5写到寄存器eax中。

参数传递也以类似的方式处理。还是以i386为例,为每个可能的参数指定一个寄存器——寄存器ebx、ecx、edx、esi和edi顺序存储前5个参数。对于极少数参数超过5个的系统调用,则使用单个寄存器指向保存所有参数的用户空间缓存。当然,大部分系统调用只包含几个参数。

虽然基本思想是一致的,但不同体系结构处理系统调用的方式不同。作为一名系统程序员,通常不需要了解内核是如何处理系统调用的。系统调用已经集成到各种体系结构的标准调用规范中,并通过编译器和C库自动处理。

1.1.4 C库
C库(libc)是UNIX应用程序的核心。即使你是使用其他语言编程,通常还是会通过高级语言封装的C库来提供核心服务,以方便系统调用。在现代Linux系统中,C库由GNU libc提供,简称glibc,发音是[gee-lib-see],或者有时发作[glib-see]。

GNU C库的功能远远超出了其名字的范畴。glibc中,除了标准C库,还提供了系统调用封装、线程支持和基本应用工具。

1.1.5 C编译器
在Linux中,标准C编译器是由GNU编译器工具集(GNU Compiler Collection,gcc)提供的。最初,gcc是GNU版的C编译器cc,因此,gcc表示GNU C编译器(GNU C Compiler)。随着时间推移,gcc支持越来越多的语言。时至今日,gcc已经成了GNU编译器家族的代名词。此外,gcc还表示C编译器二进制程序。除非特别指明,本书中提到gcc时,都是指gcc应用程序。

因为编译器辅助实现了标准C(参阅1.3.2小节)和系统ABI(参阅1.2.1小节和1.2.2小节),在UNIX系统(包括Linux)中所使用的编译器和系统编程紧密相关。

C++

本章把C语言作为系统编程的通用语言,但是C++语言也功不可没。

今天,C++在系统编程中的地位仅次于C语言。由于历史原因,比起C++,Linux开发人员更倾向于使用C语言:核心库、守护进程、工具箱以及Linux内核都是用C语言实现的。在非Linux环境中,C++语言作为“C语言的升级”,其优势是显而易见的,但是在Linux环境中,C++的地位还是逊于C。

尽管如此,本书给出的大部分相关的C语言代码都可以替换成C++。C++确实可以作为C语言的替代,适合任何系统编程工作:C++代码可以链接C代码,调用Linux系统调用,还可以充分利用glibc。

比起C,C++还为系统编程奠定了另外两块基石:标准的C++库和GNU C++编译器。标准的C++库实现了C++系统接口以及ISO C++11标准,由libstdc++库提供(有时写作libstdcxx)。GNU C++编译器是Linux系统为C++提供的标准编译器,由二进制程序g++提供。

时间: 2025-01-01 12:43:39

《Linux系统编程(第2版)》——第1章 入门和基本概念 1.1 系统编程的相关文章

《R绘图系统(第2版)》一1.2 R绘图系统的结构

1.2 R绘图系统的结构 这一节简要阐述了R 绘图函数库中的函数是如何组织的,以使用户能够了解怎样开始寻找一个特定的函数. 在R绘图工具库中占据核心地位的是grDevices包,该包同时也被称为绘图引擎.grDevices包提供了一系列R中的基本绘图函数,如选择颜色和字体以及选择绘图输出格式.尽管几乎所有的R绘图应用都使用了grDevices包,这其中绝大部分只需要通过学习一些基本知识即可掌握,所以关于该包中绘图函数的细节被安排在本书第3部分介绍. 在绘图引擎的基础上直接搭建了两个包:grap

《MapReduce 2.0源码分析与编程实战》一第2章 入门

第2章 入门 HBase实战本章涵盖的内容 连接到HBase和定义表 与HBase交互的基本命令 HBase的物理数据模型和逻辑数据模型 基于复合行键的查询 下面几章的一个目标是教你如何使用HBase.作为一名应用开发人员,首先你要适应HBase的特性.你将学习HBase的逻辑数据模型(logical data model),访问HBase的各种方式,以及如何使用这些API的细节.另外一个目标是教你进行HBase模式(schema)设计.HBase有着和以往关系型数据库不同的物理数据模型(phy

《JavaScript入门经典(第6版)》——第1章 JavaScript简介 1.1 Web脚本编程基础

第1章 JavaScript简介 JavaScript入门经典(第6版) 本章主要内容包括: 服务器端和客户端编程 JavaScript如何改善Web页面 JavaScript的历史 文档对象模型(DOM)基础知识 window和document对象 如何使用JavaScript给Web页面添加内容 如何利用对话框提示用户 与只有文本内容的祖先相比,现代的Web几乎是完全不同的,它包含了声音.视频.动画.交互导航等很多元素,而JavaScript对于实现这些功能扮演了非常重要的角色. 在第1章中

360系统急救箱U盘版详细使用方法

  360急救盘是奇虎360公司开发的一款基于linux的应急操作系统,其安装简单,使用方便.与winpe相比,具有更稳定.兼容性更好.网络支持能力更佳等优点.让你在系统崩溃的时候也能救资料.装系统,集成360重装大师U盘版,360急救箱U盘版,让您不需要拥有非常专业的电脑知识也能轻松应对系统崩溃的大难题. 通常情况下,当电脑中招后,在系统的启动序列上,杀毒软件位于木马病毒运行之后.这点导致杀毒软件在处理已感染病毒的电脑时存在技术劣势.因为木马优先运行的驱动可以造成杀毒软件加载失败,木马还会使用

Linux Deepin 11.06正式版发行

Linux Deepin一种流行和​​活跃的中国社区发行版,基于Ubuntu GNOME桌面和很多可用性方面的改进.从热情的志愿者的卓越贡献,Linux Deepin 11.06已被释放.它是基于Ubuntu的11.04,但仍然使用GNOME2,它的特点Deepin自主研发的软件中心.喜欢默认的字体大小的这个新版本的外观和感觉都响应来自用户社区的要求进行了调整,以及简体和繁体中文与一个漂亮的皮肤输入法. LibreOffice是安装在默认情况下,但该软件是专门从Deepin中心提供一个的办公套件

《Linux防火墙(第4版)》——2.4 过滤传入的数据包

2.4 过滤传入的数据包 外部网卡I/O对中的输入端.输入规则集,对于保护您的站点而言,是更值得注意的.就像前面提到的那样,您能够基于源地址.目的地址.源端口.目的端口.TCP状态标志以及其他标准进行过滤. 您将在后面的章节中了解到所有这些信息. 2.4.1 远程源地址过滤 在数据包层面,唯一确定IP数据包发送者的方式便是数据包报头的源地址.这个事实为源地址欺骗(source address spoofing)提供了可能,发送者将一个并非他/她真实地址的错误地址放在报文的相应源地址域里.该地址可

《Linux防火墙(第4版)》——导读

前言 欢迎阅读本书.本书介绍了在运行Linux的计算机上建立防火墙所需要的各方面内容.在开始介绍Linux下的防火墙iptables以及最新的nftables之前,本书会介绍一些基础的内容,包括网络.IP以及安全. 本书是构建Linux防火墙的权威指南,包括如何使用Linux iptables/nftables来实现防火墙安全的主题.本书共分三大部分.第1部分为数据包过滤以及基本的安全措施,其内容有:数据包过滤防火墙的预备知识.数据包过滤防火墙概念.传统的Linux防火墙管理程序iptables

Linux环境下安装解压缩版MySQL5.5

Linux环境下安装解压缩版MySQL5.5成功完成. 本来是想在www.mysql.com网上下载安装的mysql的,看了几个版本全是解压的.就在网上搜索了一些资料进行了解压版的安装. 下面给大家说一下设置的过程. 首先参考了:http://sheng.iteye.com/blog/830209 的博客.   (由于没有安装成功,所以在其博客的基础上做了相应的修改如下) 1.下载MySQL免安装版/二进制版软件(不用编译)     按照自己系统选择 http://www.mysql.com/d

《嵌入式Linux基础教程(第2版)》——2.4 嵌入式Linux发行版

2.4 嵌入式Linux发行版 到底什么是Linux发行版? Linux内核完成系统引导后,它会找到并挂载一个根文件系统.一旦合适的根文件系统被成功挂载,启动脚本会启动很多系统需要的程序和实用工具.这些程序一般会调用其他程序来完成具体的任务,例如生成一个登录shell.初始化网络设备接口和运行用户的应用程序.每一个程序都有一些必须由系统中其他成员来满足的具体需求(一般称为依赖关系).大多数的Linux应用程序都依赖一个或多个系统程序库.还有一些程序需要配置文件和日志文件,诸如此类.总的来说,即使