找回密码
 立即注册
首页 业界区 安全 Linux系统编程1核心概念1.1什么是系统编程? ...

Linux系统编程1核心概念1.1什么是系统编程?

东新 7 小时前
1 核心概念

本章概述了系统编程的全貌,并介绍了 Unix 的基本背景信息。我们首先会探讨什么是系统程序,以及它们与其他类型的程序有何不同。接下来,我将介绍 Unix 操作系统家族的许多基本概念,最后简要讨论 Unix 和 C 编程语言的历史和标准化。
在探讨构成 Unix 的各种概念时,我们首先会探讨内核,因为它本质上是 Unix 系统的核心。之后,我们会讨论 Unix Shell,它是 Unix 系统中可编程、可交互的用户界面,与 Unix 内核相互独立且截然不同。之后,我们将介绍用户和组的概念。然后,我会解释 Unix 中特权指令和非特权指令的区别,是如何使内核能够安全高效地管理资源的。接下来,我将介绍用户进程的概念(它表示由内核管理的正在运行的用户程序)以及线程,它们是 Unix 中一种特殊的进程类型。我还将解释环境列表的概念,它是传递给新进程的一组变量和值。此外,我还将描述 Unix 目录层次结构,并概述文件、目录和权限。
​​任何 Unix 系统的一个重要部分是其在线文档,它在本书中学习系统编程的过程中起着至关重要的作用。我们还将在本章介绍它的组织和使用方法。
1.png

1.1 什么是系统编程?

人们学习编写的第一个程序都很简单,但尽管它们很简单,我们仍然可以用它们来解释什么是系统编程。最简单的、真正执行操作的程序没有输入,只是在屏幕上打印一条消息。其中一个程序就是随处可见的“Hello, World”程序,你很可能在作为程序员的开发生涯之初就编写过它。

  • hello_world.c
  1. #include <stdio.h>
  2. void main()
  3. {
  4.     printf("hello, world.\n");
  5. }
复制代码
第一行是一个 include 指令,以关键字 #include 开头,后跟一个文件说明。它告诉 C 预处理器在程序的该位置读取文件(在本例中为 C 头文件 stdio.h)的内容。我们需要执行该操作,因为主程序会调用 C 函数 printf(),该函数的声明位于 stdio.h 中。如果没有它,编译器就无法判断 printf() 是否被正确调用。C 预处理器必须先找到头文件才能读取它,而头文件可能位于许多可能的位置。文件名周围的尖括号 () 告诉预处理器它位于它搜索的标准位置之一。
1.1.1 输入和输出

printf() 函数是 C 语言中在屏幕上打印信息的一种方式。我使用“屏幕”一词作为更专业的术语“终端窗口”的同义词。在这个简单的例子中,printf() 的参数是一个字符串“hello, world.\n”。\n 是换行符,它会使它后面的字符出现在屏幕上下一行的开头。
  1. # gcc -o hello_world hello_world.c
  2. # ./hello_world
  3. hello, world.
复制代码
C 语言为我们提供了一个非常强大的工具 printf(),让我们无需学习太多终端和其他技术知识,就能编写将内容打印到屏幕上的程序。
让我们更进一步。上面的程序输出文本,但没有输入。下例同时执行输入和输出。

  • hello.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6.     char    name[256];
  7.     printf("Enter your name: ");
  8.     scanf("%255s", name);
  9.     printf("hello %s\n", name);
  10. }
复制代码
该程序首先声明一个名为 username 的字符数组,长度为 256。该数组最多可存储 255 个字符,外加一个终止符 NULL 字节。NULL 字节是代码为零的非打印字符。作为字符,它写为 \0。在许多编程语言中,字符串末尾必须有一个 NULL 字节。然后,程序会在屏幕上打印一条提示消息,要求用户输入其姓名。然后,C 语言的 scanf() 函数会从键盘读取字符,直到输入 255 个字符,或者遇到一个空格字符(空格、制表符或换行符),并将这些数据存储到 username 数组中。程序会打印 hello,然后输出该数组的内容。
scanf() 函数是 C 语言库的格式化输入函数。它默认从键盘读取输入,并遵循您指定的格式。通常,它的第一个参数是一个用双引号括起来的字符串,后跟一个或多个指针。双引号括起来的字符串称为格式规范。在本例中,它是“%255s”,它指定输入数据应存储为字符串(s 代表字符串),最大宽度为 255 个字符。格式规范后面的参数必须是指向字符数组开头的指针,该数组足够大,可以容纳 255 个字符加上一个 NULL 字节。由于在 C 语言中,数组名可以在任何需要常量指针的地方使用,因此数组用户名是一个有效的参数。
  1. # gcc -o hello hello.c
  2. # ./hello
  3. Enter your name: Andrew
  4. hello Andrew
复制代码
程序调用了 scanf() 和 printf() 函数,但它们的代码在哪里,又是如何执行的?许多初级程序员错误地认为,他们程序包含的头文件包含函数实现,因为他们只需在程序中放入适当的 #include 指令即可运行。然而,这些实现并不在头文件中。
1.1.2 C 库在 I/O 中的作用

通常,当函数未在调用它们的代码所在的文件中定义时,需要将它们链接到调用代码中。当编译器在处理文件时发现未在同一个文件中定义的函数调用,它会将该调用标记为未解析符号,因为它无法为该函数分配地址。如果发现未知的类型名称、变量名称等,也是如此。链接是为这些未解析符号分配地址的行为。
编译器不进行链接。链接器是编译器集合中用于解析未定义符号的组件。编译器集合是一组从源代码构建程序的程序。 C 语言没有提供任何内置的执行操作的功能,例如输入/输出、内存管理和字符串操作。相反,它们定义在标准库中,您可以将其链接到程序中。对于 scanf() 和 printf(),它们的定义是 C 标准库的一部分。链接器会自动搜索此库,而无需您执行任何特殊操作,从而找到函数定义。scanf() 函数调用名为 read() 的低级函数。实现 read() 的代码不属于库的一部分;它是 Unix 操作系统本身的一部分。read() 代码执行从输入设备到程序内存的实际字节传输。类似地,printf() 函数会调用名write() 的低级函数,该函数也是在操作系统内部实现的。write() 代码处理写入输出设备的所有细节。简而言之,操作系统负责执行所有与输出设备(通常是终端)之间的数据传输。
2.png

在 Unix 系统以及几乎所有现代操作系统中,许多人可以同时在系统上工作,属于不同用户的程序可以同时运行,每个程序从不同的键盘接收输入,并将输出发送到不同的显示器。每个人都会看到相同的输出,就像他们在单用户计算机上运行该程序一样。操作系统使这一切成为可能。它必须确保每个用户的程序不会相互干扰。
1.1.3 系统资源

资源是软件使用和/或修改的对象。例如,程序的输入和输出数据是资源,存储在其内部数据结构中的值也是资源。程序有权访问或修改其自身的任何资源。
在 Unix 系统中,某些资源受到保护,普通程序无法访问,只能由操作系统访问。这些受保护的资源称为系统资源。系统资源包括硬件,例如 CPU、物理内存、屏幕显示器、存储设备和网络连接。它们还包括非硬件对象,例如系统数据结构和文件。这些有时被称为软资源。下图展示了操作系统如何分层控制对系统资源的访问。
3.png

现代操作系统(例如 Unix)提供了一个接口,程序可以通过该接口请求访问系统资源。这个接口被称为应用程序编程接口 (API:application programming interface)。在计算机科学术语中,“应用程序”通常指普通用户运行的程序。API 通常由函数、类型和常量定义组成,有时还包括变量定义。操作系统提供的 API 实际上定义了应用程序向其请求服务的方式。API 中的函数被称为系统调用。
如果您熟悉面向对象编程,您可能会注意到操作系统的 API 与类接口之间存在相似之处。两者都提供了一组方法,用于仅通过一组明确定义的访问点来访问受保护的数据。
参考资料


  • 软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
  • 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
  • python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
  • Linux精品书籍下载 https://www.cnblogs.com/testing-/p/17438558.html
  • python八字排盘 https://github.com/china-testing/bazi
  • 联系方式:钉ding或V信: pythontesting
1.1.4 系统程序解释

现在,我们先来区分普通程序和系统程序。普通程序的设计使其拥有对其使用的所有资源的独占访问权限。它不处理连接显示器和键盘的复杂性,也没有意识到操作系统必须管理这些资源。
相反,直接请求操作系统 API 中公开的服务的程序称为系统程序,当我们编写这种程序时,我们就是系统编程。系统程序直接向操作系统请求资源和服务。有时,人们编写它们是为了扩展操作系统本身的功能,或提供更高级别应用程序可以使用的功能。例如,我们可以编写一个程序,从操作系统的内部时钟获取当前时间,并以各种格式显示给任何用户。这就是一个系统程序。
“系统程序”一词也适用于任何可以独立于操作系统运行并扩展其功能的程序,即使它不直接调用 API。编译器、汇编器、链接器、终端仿真器等工具被视为系统程序,它们在计算机系统中发挥着基础作用。正如 Richard Stallman 所写:“内核是操作系统的重要组成部分,但它本身毫无用处;它只能在完整的操作系统环境中运行”。
从这个角度来看,系统程序就像操作系统的扩展,尽管它们的定义有些模糊。本书的主要目的是向您展示如何编写这种性质的程序,即那些直接与操作系统交互,实际上像该系统的一部分一样运行的程序。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册