系统编程是什么

目录(?)[+]

部分摘自《Linux System Programming 》作者: Robert Love

刘建文略译(http://blog.csdn.net/keminlau)

KEY:系统论 系统编程

System Programming

过去的Unix编程是没有系统不系统之分的。即便是开发 X Window也是在系统级(system-level)编程,看到系统的所有API。现代的操作系统编程有所谓[系统级编程],使用与[应用编程]不同的API(System programming API) 。

从编程的形式和耗费心力上,系统编程与应用编程没有本质区别,这也意味着一个经验丰富的应用程序员转向系统编程难度不大。系统编程与应用编程的不同在于:

  • 第一,系统编程更接近硬件;系统程序员必须熟悉硬件环境和操作系统环境;相对的,应用程序员更多是熟悉应用的环境;
  • 第二,系统编程使用的函数库和库函数调用方法与应用编程有一些不同。比如,在调用系统调用(syscall)时使用所谓的陷入方式,也就是软中断方式。

近年来,随计算应用深化,应用编程有远离系统编程的趋向。不过,这并不能说或者预言系统编程的末日的到来。因为,有人用Javascript或C#写应用就要有人写它的解释器和运行时。 此外,操作系统代码只能使用系统级编程。

本书的一些核心问题:

  • 系统级接口(system-level interface)到底是什么?又如何编写Linux的系统级应用?
  • 内核和C库具体提供了什么给我们?
  • 如何编写优质代码?Linux又有什么已知的陷阱(tricks )?
  • Linux的系统调用是如何实现的?
  • What neat system calls are provided in Linux compared to other Unix variants? How does it all work? Those questions are at the center of this book.

Linux系统编程需要熟悉三大块内容:系统调用、C库和C编译器。

System Calls

[系统调用]就是用户空间与内核之间的函数接口,目的是为了给用户空间的程序请求内核服务和资源。与其它很多操作系统相比,Linux实现的系统调用少很多。比如,Linux为I386体系实现了300个左右的系统调用,而 Microsoft Windows据说实现数以千计的系统调用。Linux内核的不同平台实现在系统调用上存在差异,不过90%的系统调用是相同的。

Invoking system calls

出于安全性等因素,应用代码是不能够直接调用系统调用的。必须使用特殊的[陷入](trap)机制。一种“知会”内核进行工作的函数调用形式(KEMIN:证明两“系统”的耦合度较弱,比直接调用方式要弱。以系统论的角度考究syscall也很有意思)。陷入机制的具体实现也是因不同的体系而有所不同的。比如I386体系,应用代码通过触发软中断指令(int
0x80)来调用syscall。那0x80是什么呢?软件中断向量号吗?回答否。应用代码必须通过处理器的寄存器向告诉内核向量号和调用参数。比如,如果应用代码调用open(),它得置eax值5,然后把参数放在另外的五个寄存器:ebx, ecx, edx, esi, 和edi(所以系统调用至多使用五个参数),这些寄存器保存有用户空间的地址,也就是参数数据所在。

作为一位系统程序员,你一般不需干涉系统调用的过程,因为调用过程由体系定义,并且由C库和C编译器自动处理。

The C Library

C库是所有UINX应用的核心,因为无论你使用什么语言,你的代码最终还是调用C库。其它高级语言的库都是基于C库构建的,或者说是这些库是对C库的包装。现在的Linux,使用的C库是GNU libc,行话glibc。glibc不仅仅是个程序语言库,比如C标准库,它还是一个系统库,而且是一个现代操作系统库,函数涵盖了对系统调用的包装、线程支持、网络支持等。

The C Compiler

Linux的C编译器是gcc,过去gcc代表GNU C Compiler,是cc的在GNU项目的实现;现在gcc代表GNU Compiler Collection,不过gcc 仍然是C编译器的入口。Unix系统(包括Linux)使用的编译器与系统编程是高度相关的,因为编译器负责实现了C标准和系统ABI。

APIs and ABIs

无人不希望自己写的程序具有很好的移植性(portability),可以运行在不同软件平台(如操作系统或应用框架)、硬件平台(如处理器体系及载板),甚至跨平台的开发版本运行。有多种因素影响着程序的可移植性,当中就有两组不同的[系统接口]影响程序的可移植性:第一组是应用编程接口(API),另一组是应用二进制接口(ABI)。

APIs

API是两支软件在源代码级的接口。通过这个标准的接口(一般以函数形式实现),客户代码(一般称高级别的软件代码)可以调用服务代码(低级别的软件代码)。API本身是抽象的,它仅定义了一个接口,不涉入应用程序如何实现的细节。

系统论里的接口范畴

接口或者端口是两子系统边界[信息交换]的规格或约定方式,用通俗的理解就是,信息是什么样的。接口是信息的格式。

应用编程接口,就是软件系统不同组成部分衔接的约定。由于近年来软件的规模日益庞大,常常会需要把复杂的系统划分成小的组成部分,编程接口的设计十分重要。程序设计的实践中,编程接口的设计首先要使系统的职责得到合理划分。良好的接口设计可以降低系统各部分的相互依赖,提高组成单元的内聚性,降低组成单元间的耦合程度,从而提高系统的维护性和扩展性。

由于API是抽象的,必须清晰区别接口定义与接口的实现。比如[C标准库]是API,uclibc是一个实现;POSIX 是API,glibc是一个实现。

那么API一般涵盖什么样的函数呢? 这是一个很有意思的问题。比如C标准库是一种语言库,它必须非常通用,所以接口函数不能依赖软件或硬件特性;相反POSIX 是操作系统标准,它相对没那么的通用。

ABIs

API是源代码级别接口,是逻辑约定;而ABI是二进制级别接口,定义的在特定的架构上两个软件模块之间的接口的物理实现方式。这种[物理实现约定]保证二进制代码兼容,也就是保证一段目标代码能够在任何具有同样ABI的系统上都正常运作,不需要重新编译源代码。

ABI([物理实现约定]) 的内容包括调用约定(calling conventions)、字节序(byte ordering)、寄存器使用(register use)、系统调用实现方式、对象链接、库行为和二进制格式。以调用规则为例,它规定了函数如何被调用,参数如何传递,哪些寄存器被保留和哪些会被破坏,以及调用者如何提取返回的结果。

尽管曾经尝试着为特定架构下不同的操作系统(特别是i386上的Unix操作系统)定义唯一的ABI,然而到目前为止还没有取得成效。相反,包括Linux在内的操作系统都尝试定义各自独立的ABI,这些ABI和架构紧密相连。大部分的ABI涉及了机器级别的概念,如特定的寄存器或者汇编指令。因此,在Linux系统中,每一个机器架构都有自己的ABI集合,事实上,我们以机器架构的名称来称呼这些ABI,例如alpha x86-64等。

1.4 Linux编程概念、POSIX和系统库

所有的Unix系统,包括Linux系统,都提供了一个共同的抽象和接口集合,这个共同点定义了Unix。如对文件和进程的抽象、管道和套接字管理的接口等等,都是Unix的核心内容。

综上,个人理解,系统编程与应用编程的不同在于:调用的接口不同。

系统编程是什么,布布扣,bubuko.com

时间: 2024-10-12 07:56:01

系统编程是什么的相关文章

嵌入式系统编程和调试技巧

嵌入式系统的开发,软件的运行稳定可靠是非常重要的.在芯片中,软件是没有质量的,但软件的质量可以决定一颗芯片的成败.芯片设计中,性能能否满足设计要求,除了硬件设计.软硬件配合的设计技巧,对于软件来说,编程的一些技术和技巧同样重要. 本文讲述我在芯片固件开发过程中使用的一些编程调试技巧.针对在嵌入式系统开发中常见的问题,如实时系统下的同步问题,动态内存分配的内存泄漏问题,如何在编程阶段预防BUG出现,调试阶段如何及时发现问题和定位问题.总结下经验,目的是开发一个稳定运行的固件,提高开发效率,提高运行

LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程需要做的什么事情,所以特定看了UNIX环境编程和LINUX系统编程这2本书 重新梳理下整个要点. 内容: 一般而言: 如果程序类似于下面的情况: if((pid=fork())==0) { dochildtthing(); exit(0); } else if(pid>0) { dofathertt

Linux系统编程-setitimer函数

功能:linux系统编程中,setitimer是一个经常被使用的函数,可用来实现延时和定时的功能. 头文件:sys/time.h 函数原型: int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value); 参数含义: 1.which参数用来设置定时器类型,可选的值为 (1)ITIMER_REAL : 设置定时器以系统真实所花费的时间来计时,运行指定时间后发送SIGALRM信号. (

Linux系统编程笔记

写在开篇:出于对未来职业规划的考虑(其实还是一团糟),制定了一个基本的学习方向,那就是从系统编程学习API慢慢的深入内核,这是一个比较成熟的学习路线.所以从本篇开始,在这段时间会陆续记录Linux系统编程的学习笔记,除了供学习之余复习只用,同时也期望能记录初入职场摸爬滚打的第一个3年. 第一章 文件I/O 文件访问的基本调用一般是 read()和write(),但是在访问文件之前,要做的是一项很重要的工作就是:打开,没错!通过调用 open()或create()实现 #include <sys/

Linux系统编程@进程通信(一)

进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统的一个分支) POSIX进程间通信(POSIX:可移植操作系统接口,为了提高UNIX环境下应用程序的可移植性.很多其他系统也支持POSIX标准(如:DEC OpenVMS和Windows).) 现在Linux使用的进程间通信方式包括: 管道(pipe).有名管道(FIFO) 信号(signal) 消

《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h>文件中的常量. 通过cat 命令查看: [email protected]:~/Code/tlpi$ cat /usr/include/limits.h /* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 Free Software

《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)

<Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候都会发生缓冲.通过缓冲可以在一定程度上将用户空间与实际的物理设备分离,还可以减少内核访问磁盘的次数. 先来看看关于内核缓冲区高速缓冲:read和write调用在对磁盘文件进行操作的时候不会直接访问磁盘,如下图所示. 例如:write(fd, "abc", 3) write调用会将"

linux系统编程之管道(一):匿名管道(pipe)

原文地址:http://www.cnblogs.com/mickole/p/3192210.html 一,什么是管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 数据的读

Linux系统编程之访问文件夹及其文件属性

1. 文件夹操作:opendir, readdir, closedir 2. 文件属性:lstat 3. 实现功能:获取指定文件夹下所有的文件(使用递归),因此就能计算所有文件大小之类的啦... 代码示例如下: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/stat