20211314王艺达信息安全系统设计与实现学习笔记(1)

发布时间 2023-09-10 17:14:02作者: 20211314王艺达

作业要求链接

https://www.mosoteach.cn/web/index.php?c=interaction_homework&m=s_write&clazz_course_id=97072AE7-2C45-11EE-8539-1C34DA7B3F7C&id=F3080EAA-E3B7-414E-B311-938F0B8988F0&order_item=group&status=IN_PRGRS

第一章学习总结及自测

知识点归纳

什么是Unix/Linux

Unix和Linux都是操作系统,它们具有很强的相似性,因为Linux是在Unix的基础上发展起来的。

Unix

Unix是一种多用户、多任务的操作系统,最早由贝尔实验室(Bell Labs)的工程师开发。它的历史可以追溯到20世纪70年代初。Unix以其稳定性、安全性和强大的多任务处理能力而著称。它采用了分层的设计,使得用户可以同时运行多个任务,并且可以通过命令行界面来操作系统。

Unix的设计哲学强调了简洁、可重用和可扩展的原则,这也是许多现代操作系统所采用的基本思想之一。Unix也是许多其他操作系统的基础,包括Linux和macOS等。

Linux

Linux是一个类Unix操作系统的内核,最早由芬兰的计算机科学家Linus Torvalds在1991年创建。Linux内核采用了与Unix类似的设计原则,并且完全兼容POSIX(可移植操作系统接口)标准。

Linux通常指的是基于Linux内核的完整操作系统,这类系统通常包括了一个图形用户界面(如GNOME或KDE)、各种工具和应用程序。Linux也以其开放源代码的特性而著名,这意味着任何人都可以查看、修改和重新分发Linux的源代码。

Linux在服务器领域非常流行,因为它稳定、安全,并且能够高效地运行在各种硬件平台上。此外,许多嵌入式设备和超级计算机也使用了Linux作为其操作系统。

Unix和Linux都是强大的操作系统,它们在计算机科学和工业界中扮演着重要的角色。它们提供了强大的工具和环境,使得开发者和用户可以高效地进行工作和学习。

Linux启动

在启动期间,Linux启动加载程序首先会定位Linux内核映像(文件)。然后:

加载BOOT+SETUP至实模式内存的0x90000处。

加载Linux内核至高端内存的1MB处。

对于常见的Linux内核映像,该加载程序还会将初始ramdisk映像initrd加载到高端内存中。然后转移控制权,运行0x902000处的SETUP代码,启动Linux内核。首次启动时,Linux内核会将initrd作为临时根文件系统,在initrd上运行。Linux内核将执行一个sh脚本,该脚本指示内核加载实际根设备所需的模块。当实际根设备被激活并准备就绪时,内核将放弃初始ramdisk,将实际根设备挂载为根文件系统,从而完成Linux内核的两阶段启动。

Linux运行级别

Linux内核以单用户模式启动。它可以模仿System V Unix的运行级别,以多用户模式运行。然后,创建并运行INIT进程P1,后者将创建各种守护进程和供用户登录的终端进程。之后,INIT进程将等待任何子进程终止。

登录进程

各登录进程将在其终端上打开三个文件流:stdin(用于输入),stdout(用于输出),stderr(用于错误输出)。然后等待用户登录。在使用X-window作为用户界面的Linux系统上,X-window服务器通常会充当用户登录界面。用户登录后,(伪)终端默认属于用户。

命令执行

登录后,用户进程通常会执行命令解释程序sh,后者将提示用户执行命令。sh将直接执行一些特殊命令,如cd(更改目录)、exit(退出)、logout(注销)、&。

使用Ubuntu Linux

Ubuntu Linux的特性

(1)在台式机或笔记本电脑上安装Ubuntu时,需要输入用户名和密码来创建一个默认主目录为“/home/username”的用户账户。当Ubuntu启动时,它会立即在用户环境中运行,因为其已自动登录默认用户。

(2)出于安全原因,用户应为普通用户,而不是根用户或超级用户。
要运行任何特权命令,用户必须输入
sudo command

(3)用户的“PATH”(路径)环境变量设置通常不包括用户的当前目录。为在当前目录下运行程序,用户每次必须输入./a.out。为方便起见,用户应更改路径设置,以包含当前目录。在用户的主目录中,创建一个包含以下代码的.bashrc文件:
PATH=$PATH:./

用户每次打开伪终端时,sh都会先执行.bashrc文件来设置路径,以包含当前工作目录。
(4)很多用户可能都安装了64位的Ubuntu Linux。本书中的一些编程练习和作业是针对32位机器的。在64位Linux下,使用
gcc -m32 t.c # compile t.c into 32-bit code

生成32位代码。若64位Linux不采用-m32选项,则用户必须安装适用于gcc的附加支持插件,才能生成32位代码。
(5)Ubuntu具有友好的GUI用户界面。许多用户都习惯于使用GUI,以至于产生了过度依赖,这往往需要反复拖动和点击指向设备,从而浪费了大量时间。在系统编程中,用户还需要学习如何使用命令行和sh脚本,它们比GUI要通用和强大得多。

Unix/Linux文件系统组织

Unix/Linux命令

Unix/Linux中最常用的命令:

ls:ls dirname:列出CWD或目录的内容。

cd dirname:更改目录。

pwd:打印CWD的绝对路径名。

touch filename:更改文件名时间戳(如果文件不存在,则创建文件)。

cat filename:显示文件内容。

cp src dest:复制文件

mv src dest:移动或重命名文件。

mkdir dirname:创建目录。

rmdir dirname:移除(空)目录。

rm filename:移除或删除文件。

ln oldfile newfile:在文件之间创建链接。

find:搜索文件。

grep:搜索文件中包含模式的行。

ssh:登录到远程主机。

gzip filename:将文件压缩为.gz文件。

tar -zcvf file.tgz.:从当前目录创建压缩tar文件。

tar -zxvf file.tgz.:从.tgz文件中解压文件。

man:显示在线手册页。

zip file.zip filenames:将文件压缩为.zip文件。

unzip file.zip:解压.zip文件。

学习自测

第二章学习总结及自测

Linux中的文本编辑器

Vim

vim(Linux Vi和Vim Editor 2017)是Linux的标准内置编辑器。它是Unix原始默认vi编辑器的改进版本。与其他大多数编辑器不同,vim有3种不同的操作模式,分别是

命令模式:用于输入命令
插入模式:用于输入和编辑文本。
末行模式:用于保存文件并退出。

vim启动时,处于默认的命令模式,在该模式下,大多数键表示特殊命令。移动光标的命令键示例如下:

h:将光标向左移动一个字符

l:将光标向右移动一个字符

j:将光标向下移动一个字符

k:将光标向上移动一个字符
在X-window中使用vim时,也可以通过箭头键来完成光标的移动。要输入文本进行编辑,用户必须输入i(插入)或a(追加)命令将vim切换到插入模式:

i:切换到插入模式,插入文本。

a:切换到插入模式,追加文本。
要退出插入模式,请按ESC键一次或多次。在命令模式下,输入“:”进入末行模式,将文本保存为文件或退出vim:

:w:写入(保存)文件。

:q:退出vim。

:wq:保存并退出。

:q!:不保存更改,强制退出。
虽然许多Unix用户已经习惯了vim不同的操作模式,但是其他用户可能认为与其他基于图形用户界面(GUI)的编辑器相比,vim使用起来既不自然也不方便。以下类型的编辑器属于通常所说的所见即所得(WYSIWYG)编辑器。在WYSIWYG编辑器中,用户可以输入文本,用箭头键移动光标,和普通的文本输入一样。通常,通过输入一个特殊的meta键,接着输入一个字母键即可创建命令。例如:

Ctrl+C:中止或退出。

Ctrl+K:删除行到缓冲区。

Ctrl+Y:从缓冲区内容中复制或粘贴。

Ctrl+S:保存已编辑文本等。

程序开发

程序开发步骤

(1)创建源文件;
全局变量、局部变量、静态变量、自动变量和寄存器变量。
(2)用gcc把源文件转换成二进制可执行文件。
gcc t1.c t2.c
(3)gcc的步骤:

1.将C源文件转换为汇编代码文件,即将.c文件转为.s文件。

2.将汇编代码转换为目标代码,即将.s文件转为.o文件。
每个.o文件包含:

一个文件头
一个代码段
一个数据段
一个BSS段
指针、数据和重定位信息
符号表

3.链接。

将.o文件的所有代码段组合成单一代码段。
将所有数据段组合成单一数据段。
将所有BSS段组合成单一bss段。
使用.o文件的重定位信息调整组合指针、数据和bss段的偏移量。
用符号表来解析各个.o文件之间的交叉引用。

静态与动态链接

这是创建二进制可执行文件的两种方式。

静态库的特点:
链接器将所有必要的库函数代码和数据纳入a.out文件中。这使得a.out文件完整、独立,但通常非常大。
动态链接的优点:

减小每个a.out文件大小;
许多执行程序共享相同库函数;
修改库函数无需重新编译源文件。
动态链接所用的库称为动态链接库(DLL)。它们在Linux中称为共享库(.so文件)。动态加载(DL)库是指按需加载的共享库,可用作插件和动态加载模块。

可执行文件格式

1.二进制可执行平面文件
2.a.out可执行文件
3.ELF可执行文件

a.out文件的内容

1.文件头
2.代码段
3.数据段
4.符号表

程序执行过程

1.读取a.out文件头,以确定所需总内存大小;
2.sh从总大小中分配一个内存区给执行映像;
3.接着,sh放弃旧映像,开始执行新映像
4.执行从crt0.o开始,调用main()

程序终止

1.正常终止
2.异常终止

C语言中的函数调用

32位GCC中运行时堆栈使用情况

1.进程执行映像

2.每个CPU都有以下寄存器或同等寄存器:

PC(IP):指向CPU要执行的下一条指令。
SP(SP):指向栈顶。
FP(BP):指向当前激活函数的栈帧。
返回值寄存器(AX):函数返回值的寄存器。

3.main函数由crt0.o调用。

4.每个函数入口,编译后的代码完成如下功能:

将FP压栈,在堆栈上保存CPU的FP寄存器。
让FP指向保存的FP#建立栈帧。
向下移动SP为堆栈上的自动局部变量分配空间。
编译后的代码可能继续向下移动SP,在堆栈上分配一些临时工作空间,用temps表示。

链接库

创建静态链接库

gcc -c mysum.c
ar rcs libmylib.a mysum.o
gcc -static t.c -L. -lmylib
a.out

创建动态链接库

gcc -c -fPIC mysum.c
gcc -shared -o libmylib.so mysum.o
gcc t.c -L. -lmylib
export LD_LIBRARY_PATH=./
a.out

GDB调试工具

GDB断点设置指令总结:

(gdb)break 7 //以行号设置断点
(gdb)break function_name //以函数名设置断点
(gdb)clear 行号 //删除这行的断点
(gdb)clear 函数名 //删除该函数的断点
(gdb)delete breakpoints n //删除第n次(指定编号)设置的断点
(gdb)clear //删除程序中所有的基于行设置的断点
(gdb)delete //删除程序中所有的断点
(gdb)r //执行程序
(gdb)n //单步调试
(gdb)c //执行到下一个断点
(gdb)print 变量或表达式 //打印变量或表达式当前的值。
(gdb)print 变量=值 //对变量进行赋值
(gdb)whatis 变量或表达式 //显示变量类型
(gdb)set variable 变量=值 //变量赋值

C语言结构体

(1)结构体是包括变量或数据对象集合的复合数据类型。C语言结构体类型由 struct 关键字定义。

next:指向下一个节点结构体的指针;

key:一个整数;

name:一个由64个字符组成的数组。

(2)定义结构体时,该结构体的每个字段都必须具有一个·1编译器已知的类型,但自引用指针除外;

每个C语言结构体数据对象都分配了一个连续内存块。C语言结构体的单个字段通过使用 .operater (.运算符)访问。

x.next:指向另一个NODE类型对象的指针;

x.key:这是一个整数;

x.name:这是64个字符组成的数组。

运行时,每个字段相对于结构体起始地址的偏移量进行访问。

(3)一个结构体的大小可以根据sizeof(struct type)确定。C编译器将计算该结构体的总字节数大小。由于内存排列受限制,C编译器可能会用额外字节填充结构体的某些字段。如果需要,用户可以用PACKED属性定义C语言结构体。

(4)假设“NODE x , y"为两个相同类型的结构体,除了复制粘贴,还可以通过C语句y=x 将 x 分配给 y ;

(5)C语言联合体与结构体类似。要定义一个联合体,只需要将关键字 struct 替换成关键字union。

学习自测