mirror of
https://github.com/Didnelpsun/CS408.git
synced 2026-06-16 23:17:21 +08:00
更新概述
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,4 +1,7 @@
|
||||
*.pdf
|
||||
/Code/.vs/
|
||||
/Code/Debug/
|
||||
/Code/x64/
|
||||
*/.vs/
|
||||
*/.idea/
|
||||
*/Debug/
|
||||
*/x64/
|
||||
*/out/
|
||||
*/cmake-build-debug/
|
||||
11
CPP-Code/CMakeLists.txt
Normal file
11
CPP-Code/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
# CMakeList.txt: CPP-Code 的 CMake 项目,在此处包括源代码并定义
|
||||
# 项目特定的逻辑。
|
||||
#
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
project ("CPP-Code")
|
||||
|
||||
# 将源代码添加到此项目的可执行文件。
|
||||
add_executable (CPP-Code "source/main.cpp")
|
||||
|
||||
# TODO: 如有需要,请添加测试并安装目标。
|
||||
15
CPP-Code/CMakeSettings.json
Normal file
15
CPP-Code/CMakeSettings.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
8
CPP-Code/head/head.h
Normal file
8
CPP-Code/head/head.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// 初始化最大长度
|
||||
#define MAXSIZE 5
|
||||
// 定义默认值
|
||||
#define DEFAULTELEM '0'
|
||||
// 定义最大值
|
||||
#define INFINITY 32767
|
||||
// 定义默认数据类型
|
||||
typedef char element_type;
|
||||
161
CPP-Code/head/link_list.h
Normal file
161
CPP-Code/head/link_list.h
Normal file
@@ -0,0 +1,161 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include "head.h"
|
||||
|
||||
// 单链表结点
|
||||
typedef struct LinkListNode {
|
||||
element_type data;
|
||||
struct LinkListNode* next;
|
||||
} LinkListNode, *LinkList;
|
||||
|
||||
// 由于C语言无法参数赋值,所以必须借助一个中间变量完成
|
||||
// 初始化有头节点单链表
|
||||
int InitLinkListWithHead(LinkList &list) {
|
||||
list = (LinkListNode*)malloc(sizeof(LinkListNode));
|
||||
if (list) {
|
||||
list->data = NULL;
|
||||
list->next = nullptr;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
printf("InitLinkListWithHead:分配空间失败!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化无头节点单链表
|
||||
int InitLinkListWithoutHead(LinkList &list) {
|
||||
list = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 创建有头节点单链表
|
||||
LinkList CreateLinkListWithHead() {
|
||||
auto list = (LinkListNode*)malloc(sizeof(LinkListNode));
|
||||
if (list) {
|
||||
list->data = NULL;
|
||||
list->next = nullptr;
|
||||
}
|
||||
else {
|
||||
printf("CreateLinkListWithHead:分配空间失败!");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// 创建无头节点单链表
|
||||
LinkList CreateLinkListWithoutHead() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// 判断有头节点单链表是否为空
|
||||
int EmptyLinkListWithHead(LinkList list) {
|
||||
if (list->next) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 判断无头节点单链表是否为空
|
||||
int EmptyLinkListWithoutHead(LinkList list) {
|
||||
if (list) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 插入有头节点单链表元素
|
||||
// 0号节点是头节点
|
||||
int InsertLinkListWithHead(LinkList list, int index, element_type elem) {
|
||||
if (index < 1) {
|
||||
printf("InsertLinkListWithHead:插入索引值过小!\n");
|
||||
return 1;
|
||||
}
|
||||
// 定义一个结点指针p指向当前扫描到的结点
|
||||
LinkListNode* p;
|
||||
// 定义一个变量i表示当前扫描到的结点的索引号
|
||||
int i = 0;
|
||||
// 将链表头结点指向p,为第0个结点
|
||||
p = list;
|
||||
// 循环遍历到达指定索引号的单链表的结点
|
||||
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
|
||||
while (p->next != NULL && i < index - 1) {
|
||||
p = p->next;
|
||||
i++;
|
||||
}
|
||||
// 如果此时i小于index-1,表示遍历完还没有到达对应的索引
|
||||
if (i < index - 1) {
|
||||
printf("InsertLinkListWithHead:插入索引值过大!\n");
|
||||
return 1;
|
||||
}
|
||||
// 此时i==index-1
|
||||
LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
|
||||
if (s) {
|
||||
s->data = elem;
|
||||
// 将p原来的后继给新的结点
|
||||
s->next = p->next;
|
||||
p->next = s;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
printf("InsertLinkListWithHead:分配内存失败!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 插入无头节点单链表元素
|
||||
// C语言也无法调用这个函数
|
||||
int InsertLinkListWithoutHead(LinkList list, int index, element_type elem) {
|
||||
if (index < 0) {
|
||||
printf("InsertLinkListWithoutHead:插入索引值过小!\n");
|
||||
return 1;
|
||||
}
|
||||
if (index == 0) {
|
||||
LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
|
||||
if (s) {
|
||||
s->data = elem;
|
||||
// 将s的后继设为list指针
|
||||
s->next = list;
|
||||
// 将list指针设置为s指针
|
||||
list = s;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
printf("InsertLinkListWithoutHead:分配内存失败!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// 定义一个结点指针p指向当前扫描到的结点
|
||||
LinkListNode* p;
|
||||
// 定义一个变量i表示当前扫描到的结点的索引号
|
||||
int i = 0;
|
||||
// 将链表头结点指向p,为第0个结点
|
||||
p = list;
|
||||
// 循环遍历到达指定索引号的单链表的结点
|
||||
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
|
||||
while (p->next != NULL && i < index - 1) {
|
||||
p = p->next;
|
||||
i++;
|
||||
}
|
||||
// 如果此时i小于index-1,表示遍历完还没有到达对应的索引
|
||||
if (i < index - 1) {
|
||||
printf("InsertLinkListWithoutHead:插入索引值过大!\n");
|
||||
return 1;
|
||||
}
|
||||
// 此时i==index-1
|
||||
LinkListNode* s = (LinkListNode*)malloc(sizeof(LinkListNode));
|
||||
if (s) {
|
||||
s->data = elem;
|
||||
// 将p原来的后继给新的结点
|
||||
s->next = p->next;
|
||||
p->next = s;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
printf("InsertLinkListWithoutHead:分配空间失败!\n");
|
||||
}
|
||||
}
|
||||
255
CPP-Code/head/sequence_list.h
Normal file
255
CPP-Code/head/sequence_list.h
Normal file
@@ -0,0 +1,255 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include "head.h"
|
||||
|
||||
#pragma warning(disable:6385)
|
||||
#pragma warning(disable:6386)
|
||||
|
||||
// 顺序表
|
||||
class SequenceList {
|
||||
public:
|
||||
element_type *data{};
|
||||
int length{};
|
||||
// 插入函数
|
||||
virtual bool Insert(int index, element_type elem);
|
||||
// 打印函数
|
||||
void Printf();
|
||||
// 循环插入函数
|
||||
bool LoopInsert(element_type *elem, int start, int end);
|
||||
// 删除函数
|
||||
bool Delete(int index, element_type &elem);
|
||||
// 多个删除函数
|
||||
bool MultiDelete(int index, int len, element_type *elem);
|
||||
// 按位获取元素
|
||||
element_type GetElem(int index);
|
||||
// 按值获取元素
|
||||
int Locate(element_type elem);
|
||||
// 判空
|
||||
bool Empty();
|
||||
// 销毁
|
||||
bool Destroy();
|
||||
};
|
||||
|
||||
// 静态顺序表
|
||||
class StaticSequenceList: public SequenceList{
|
||||
public:
|
||||
element_type data[MAXSIZE]{};
|
||||
int length;
|
||||
// 构造函数
|
||||
StaticSequenceList();
|
||||
// 插入函数
|
||||
bool Insert(int index, element_type elem) override;
|
||||
};
|
||||
|
||||
// 动态顺序表
|
||||
class DynamicSequenceList: public SequenceList{
|
||||
public:
|
||||
// 给一个指针来分配动态数组
|
||||
element_type *data;
|
||||
int length;
|
||||
// 已分配的最大容量
|
||||
int max_size;
|
||||
// 构造函数
|
||||
DynamicSequenceList();
|
||||
// 插入函数
|
||||
bool Insert(int index, element_type elem) override;
|
||||
|
||||
private:
|
||||
// 分配其他地址增长动态顺序表的数据空间长度
|
||||
bool OtherIncrease(int len);
|
||||
// 重新分配地址增长动态顺序表的数据空间长度
|
||||
bool ReIncrease(int len);
|
||||
};
|
||||
|
||||
StaticSequenceList::StaticSequenceList() : SequenceList() {
|
||||
this->length=0;
|
||||
}
|
||||
|
||||
DynamicSequenceList::DynamicSequenceList() : SequenceList() {
|
||||
// 初初始化动态顺序表长度为0
|
||||
this->max_size=0;
|
||||
this->length = 0;
|
||||
// 申请一片连续的存储空间
|
||||
auto* space = (element_type*)malloc(MAXSIZE * sizeof(element_type));
|
||||
if (space) {
|
||||
this->data = space;
|
||||
this->max_size = MAXSIZE;
|
||||
}
|
||||
else {
|
||||
printf("InitSequenceList:分配空间失败!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void SequenceList::Printf() {
|
||||
for (int i = 0; i < this->length; i++) {
|
||||
printf("第%d个元素值为%c\n", i + 1, this->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool DynamicSequenceList::OtherIncrease(int len) {
|
||||
if (len <= 0) {
|
||||
printf("OtherIncrease:申请空间应该大于0!\n");
|
||||
return false;
|
||||
}
|
||||
// 申请一片连续的存储空间
|
||||
int new_length = this->max_size + len;
|
||||
auto* space = (element_type*)malloc(new_length * sizeof(element_type));
|
||||
if (space) {
|
||||
// 建立中间变量
|
||||
this->data = space;
|
||||
element_type* temp = this->data;
|
||||
for (int i = 0; i < this->length; i++) {
|
||||
this->data[i] = temp[i];
|
||||
}
|
||||
this->max_size = new_length;
|
||||
free(temp);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
printf("OtherIncrease:重新分配空间失败!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DynamicSequenceList::ReIncrease(int len) {
|
||||
if (len <= 0) {
|
||||
printf("ReIncrease:申请空间应该大于0!\n");
|
||||
return false;
|
||||
}
|
||||
// 申请一片连续的存储空间
|
||||
int new_length = this->max_size + len;
|
||||
auto* space = (element_type*)realloc(this->data, new_length * sizeof(element_type));
|
||||
if (space) {
|
||||
this->data = space;
|
||||
this->max_size += len;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
this->max_size = 0;
|
||||
this->length = 0;
|
||||
printf("ReIncrease:分配其他地址空间失败!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SequenceList::Insert(int index, element_type elem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StaticSequenceList::Insert(int index, element_type elem) {
|
||||
// 当静态顺序表已经满了就不能插入任何元素
|
||||
if (this->length >= MAXSIZE) {
|
||||
printf("Insert:静态顺序表空间不足,插入失败!\n");
|
||||
return false;
|
||||
}
|
||||
// 索引位置从0开始,所以可以插入的范围是0到list->length
|
||||
if (index > this->length || index < 0) {
|
||||
printf("Insert:插入索引%d超过索引范围!\n", index);
|
||||
return false;
|
||||
}
|
||||
// 从最后一个元素开始交换后移,list->length是空的
|
||||
for (int i = this->length; i > index; i--) {
|
||||
this->data[i] = this->data[i - 1];
|
||||
}
|
||||
this->data[index] = elem;
|
||||
this->length++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicSequenceList::Insert(int index, element_type elem) {
|
||||
if (index > this->length || index < 0) {
|
||||
printf("Insert:插入索引%d超过索引范围!\n", index);
|
||||
return false;
|
||||
}
|
||||
// 当动态顺序表已经满了,需要新增一个位置
|
||||
// 为了避免索引无效而多增加一个空间,所以放在检查索引值的后面
|
||||
if (this->length >= MAXSIZE) {
|
||||
bool result = this->ReIncrease(1);
|
||||
if (!result) {
|
||||
printf("Insert:申请空间失败!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = this->length; i > index; i--) {
|
||||
this->data[i] = this->data[i - 1];
|
||||
}
|
||||
this->data[index] = elem;
|
||||
this->length++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SequenceList::LoopInsert(element_type *elem, int start, int end) {
|
||||
for (int i = 0; i < end; i++) {
|
||||
bool result = this->Insert(i, elem[i + start]);
|
||||
if (!result) {
|
||||
printf("LoopInsert:循环插入失败!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SequenceList::Delete(int index, element_type &elem) {
|
||||
if (index >= this->length || index < 0) {
|
||||
printf("Delete:删除索引超过索引范围!\n");
|
||||
return false;
|
||||
}
|
||||
elem = this->data[index];
|
||||
for (int i = index; i < this->length; i++) {
|
||||
this->data[i] = this->data[i + 1];
|
||||
}
|
||||
this->length--;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SequenceList::MultiDelete(int index, int len, element_type *elem) {
|
||||
if (index + len >= this->length || index < 0) {
|
||||
printf("MultiDelete:删除索引超过索引范围!\n");
|
||||
return false;
|
||||
}
|
||||
for (int i = index; i < this->length - len; i++) {
|
||||
if (i < index + len) {
|
||||
elem[i - index] = this->data[i];
|
||||
}
|
||||
this->data[i] = this->data[i + len];
|
||||
}
|
||||
this->length -= len;
|
||||
return true;
|
||||
}
|
||||
|
||||
element_type SequenceList::GetElem(int index) {
|
||||
if (index >= this->length || index < 0) {
|
||||
printf("GetElem:查找索引超过索引范围!\n");
|
||||
return DEFAULTELEM;
|
||||
}
|
||||
return this->data[index];
|
||||
}
|
||||
|
||||
|
||||
int SequenceList::Locate(element_type elem) {
|
||||
for (int i = 0; i < this->length; i++) {
|
||||
if (this->data[i] == elem) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
printf("Locate:未能定位到对应值的元素!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SequenceList::Empty() {
|
||||
if (this->length == 0) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SequenceList::Destroy() {
|
||||
if (this->data) {
|
||||
free(this->data);
|
||||
}
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
|
||||
9
CPP-Code/source/main.cpp
Normal file
9
CPP-Code/source/main.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "test.cpp"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
SequenceListTest();
|
||||
// LinkListTest();
|
||||
return 0;
|
||||
}
|
||||
46
CPP-Code/source/test.cpp
Normal file
46
CPP-Code/source/test.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
// ²âÊÔÎļþ
|
||||
|
||||
#include "../head/sequence_list.h"
|
||||
#include "../head/link_list.h"
|
||||
|
||||
int SequenceListTest() {
|
||||
DynamicSequenceList list;
|
||||
list.Insert(0, 'a');
|
||||
element_type a[6] = {'1','2','3','4','5','6'};
|
||||
list.LoopInsert(a, 0, 6);
|
||||
printf("%c", list.data[2]);
|
||||
/*element_type b[3] = { '9', 'a', 'e' };
|
||||
list.LoopInsert(b, 1, 2);*/
|
||||
list.Printf();
|
||||
//printf("%c", list.data[2]);
|
||||
/*list.Printf();
|
||||
printf("\n");
|
||||
int len = 2;
|
||||
element_type elem[2];
|
||||
list.MultiDelete(0, len, elem);*/
|
||||
/*list.Printf();
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("%c\n", elem[i]);
|
||||
}*/
|
||||
/*DynamicSequenceList dlist;
|
||||
InitDynamicSequenceList(&dlist);
|
||||
OtherIncreaseDynamicSequenceList(&dlist, 15);
|
||||
printf("%d", dlist.max_size);*/
|
||||
//int index = list.Locate('5');
|
||||
//printf("%d", index);
|
||||
//list.Destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinkListTest() {
|
||||
LinkList list = nullptr;
|
||||
InitLinkListWithoutHead(list);
|
||||
// InitLinkListWithHead(list);
|
||||
//LinkList list = CreateLinkListWithHead();
|
||||
// int empty = EmptyLinkListWithHead(list);
|
||||
// LinkList list = CreateLinkListWithoutHead();
|
||||
int empty = EmptyLinkListWithoutHead(list);
|
||||
printf("%d", empty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -124,6 +124,10 @@
|
||||
### 单道批处理系统
|
||||
|
||||
+ 引入脱机输入/输出技术(磁带),并用监督程序复杂控制作业的输入输出。
|
||||
+ 特点:
|
||||
+ 自动性。
|
||||
+ 顺序性。
|
||||
+ 单道性。
|
||||
+ 优点:
|
||||
+ 缓解了一定的人机速度矛盾,资源利用率得到提升。
|
||||
+ 缺点:
|
||||
@@ -133,11 +137,21 @@
|
||||
### 多道批处理系统
|
||||
|
||||
+ 操作系统正式诞生,引入中断技术,从而能并发执行程序。
|
||||
+ 特点:
|
||||
+ 多道。
|
||||
+ 宏观并行。
|
||||
+ 微观串行。
|
||||
+ 优点:
|
||||
+ 多道程序并发执行,共享计算机资源。
|
||||
+ 资源利用率提升,$CPU$和其他资源基本上忙碌,系统吞吐量增大。
|
||||
+ 缺点:
|
||||
+ 用户响应时间长,无法人机交互,不能控制作业执行。
|
||||
+ 用户响应时间长。
|
||||
+ 无法人机交互,不能控制作业执行。
|
||||
+ 问题:
|
||||
+ 处理器分配。
|
||||
+ 多道程序内存分配。
|
||||
+ $I/O$设备分配。
|
||||
+ 程序数据组织存放。
|
||||
|
||||
## 操作系统的分类
|
||||
|
||||
@@ -146,15 +160,23 @@
|
||||
### 分时操作系统
|
||||
|
||||
+ 计算机以时间片为单位轮流为各个用户/作业服务,每个用户可以通过终端与计算机交互。
|
||||
+ 特点:
|
||||
+ 同时性。
|
||||
+ 交互性。
|
||||
+ 独立性。
|
||||
+ 及时性。
|
||||
+ 优点:
|
||||
+ 用户请求可以及时响应,解决人机交互问题。
|
||||
+ 运行多个用户共同使用一台计算机,且用户对计算机的操作哦相互独立,感受不到其他人存在。
|
||||
+ 运行多个用户共同使用一台计算机,且用户对计算机的操作相互独立,感受不到其他人存在。
|
||||
+ 缺点:
|
||||
+ 不能处理紧急任务,操作系统对于每个用户都是公平的,循环给出时间片。
|
||||
|
||||
### 实时操作系统
|
||||
|
||||
+ 能优先响应紧急任务,不用等待时间片排队。
|
||||
+ 特点:
|
||||
+ 及时性。
|
||||
+ 可靠性。
|
||||
+ 优点:
|
||||
+ 能优先处理紧急任务,使用率更高。
|
||||
+ 对于紧急事件能有效高速处理,可靠性较高。
|
||||
@@ -164,40 +186,45 @@
|
||||
|
||||
### 其他操作系统
|
||||
|
||||
+ 网络操作系统:伴随计算机网络发展而但是,能连接网络中各个计算机从而能传输数据,实现网络中各种资源的共享和计算机之间的通信,如Windows NT。
|
||||
+ 网络操作系统:伴随计算机网络发展而但是,能连接网络中各个计算机从而能传输数据,实现网络中各种资源的共享和计算机之间的通信,如$Windows\,NT$。
|
||||
+ 分布式操作系统:具有分布性和并行性,系统中各个计算机地位相同,任何工作可以分布在这些计算机上,并行写协同完成任务。
|
||||
+ 个人计算机操作系统:方便个人使用的操作系统,如Windows 10、MacOS。
|
||||
+ 个人计算机操作系统:方便个人使用的操作系统,如$Windows\,10$、$MacOS$。
|
||||
|
||||
## 操作系统的运行机制
|
||||
## 操作系统的运行环境
|
||||
|
||||
### 两种指令
|
||||
### 操作系统的运行机制
|
||||
|
||||
#### 两种指令
|
||||
|
||||
+ 指令就是处理器能识别和执行的最基本命令。所以指令能控制处理器,需要给指令进行控制,对于危险的指令要更高的权限。
|
||||
+ 特权指令:
|
||||
+ 指具有特殊权限的指令,只用于操作系统或其他系统软件,一般不直接提供给用户使用。
|
||||
+ 如有关对I/O设备使用的指令、有关访问程序状态的指令、存取特殊寄存器指令。
|
||||
+ 具体而言如清内存、置时钟、分配系统资源、修改虚存的段表和页表,修改用户的访问权限等。
|
||||
+ 如有关对$I/O$设备使用的指令、有关访问程序状态的指令、存取特殊寄存器指令。
|
||||
+ 具体而言如清内存、置时钟、输入输出、分配系统资源、修改虚存的段表和页表,修改用户的访问权限等。
|
||||
+ 非特权指令:
|
||||
+ 可以被用户自由使用的指令。
|
||||
+ 如读取时钟、从内存中取数、将运算结果装入内存、算术运算等。
|
||||
+ 如读取时钟、从内存中取数、将运算结果装入内存、算术运算、寄存器清零等。
|
||||
|
||||
### 两种处理器状态
|
||||
+ 置时钟:若在用户态下执行“置时钟指令”,则一个用户进程可在时间片还未到之前把时钟改回去,从而导致时间片永远不会用完,进而导致该用户进程一直占用$CPU$,这显然不合理。
|
||||
+ 输入输出:涉及中断指令,而中断处理由系统内核负责,工作在核心态。
|
||||
|
||||
#### 两种处理器状态
|
||||
|
||||
操作系统根据处理器状态来判断是否可以使用特权指令。
|
||||
|
||||
操作系统用程序状态字寄存器PSW中的某标志位来标识当前处理器处于什么状态,如0为用户态,1为核心态。
|
||||
操作系统用程序状态字寄存器$PSW$中的某标志位来标识当前处理器处于什么状态,如$0$为用户态,$1$为核心态。
|
||||
|
||||
+ 用户态(目态):只能执行非特权指令。
|
||||
+ 核心态(管态):可以执行特权指令。
|
||||
|
||||
### 两种程序
|
||||
#### 两种程序
|
||||
|
||||
根据程序所可以使用指令的权限,程序分为两种:
|
||||
|
||||
+ 内核程序:是系统的管理者,既可以运行特权指令也可以运行非特权指令,运行在核心态。
|
||||
+ 应用程序:为了保证安全,普通应用程序只能执行非特权指令,运行在用户态。
|
||||
|
||||
## 操作系统的内核
|
||||
#### 操作系统的内核
|
||||
|
||||
操作系统的程序既然分为内核程序和应用程序,就说明有些程序是更重要的。
|
||||
|
||||
@@ -205,14 +232,106 @@
|
||||
|
||||
内核功能分为:
|
||||
|
||||
+ 时钟管理:进程等的计时功能。
|
||||
+ 中断处理:负责实现中断机制。
|
||||
+ 原语:是一种特殊的程序,是最接近硬件的部分,这种程序的运行具有原子性,运行时间短,调用次数频繁,如设备驱动、$CPU$切换等。
|
||||
+ 时钟管理:
|
||||
+ 进程等的计时功能。
|
||||
+ 时钟中断实现进程切换。
|
||||
+ 中断处理:
|
||||
+ 负责实现中断机制,提高$CPU$利用率。
|
||||
+ 只有一小部分功能属于内核,负责保护和恢复现场,转移控制权道相关处理程序。
|
||||
+ 原语:
|
||||
+ 是一种特殊的公用程序,是最接近硬件的部分。
|
||||
+ 这种程序的运行具有原子性,运行时间短,调用次数频繁。
|
||||
+ 定义原语的直接方法是关闭中断,让所有操作一致完成再打开中断。
|
||||
+ 如设备驱动、$CPU$切换、进程通信等。
|
||||
+ 系统资源管理功能:可能包含在内核中也可能不包含:
|
||||
+ 进程管理。
|
||||
+ 存储器管理。
|
||||
+ 设备管理。
|
||||
|
||||
### 中断
|
||||
|
||||
中断是内核所必要的基本功能。
|
||||
|
||||
#### 中断机制的概念
|
||||
|
||||
+ 并发批处理就需要中断机制。发生中断就表示需要操作系统介入,开展管理工作。
|
||||
+ 用户态道核心态之间的转换是通过中断实现的,且是唯一的途径,通过硬件的控制,类似$10$标志位。
|
||||
+ 而核心态道用户态之间的切换只用执行一个特权指令,将程序状态字$PSW$的标志位设置为用户态。
|
||||
|
||||
1. 当中断发生时,$CPU$立刻进入核心态。
|
||||
2. 当中断发生后,当前运行的进程暂停,并由操作系统内核对中断进行处理。
|
||||
3. 对于不同的中断信号会进行不同的处理。
|
||||
|
||||
#### 中断的分类
|
||||
|
||||
+ 内中断(异常、例外、陷入)信号来自$CPU$内部,与当前执行的命令有关,必须立刻处理,且对于无法恢复故障的需要终止进程。
|
||||
+ 自愿中断:指令中断。如系统调用时使用的访管指令(陷入指令、$trap$指令)引起的**访管中断**。
|
||||
+ 强迫中断:
|
||||
+ 硬件故障。(缺页)
|
||||
+ 软件中断。(整数除$0$)
|
||||
+ 外中断(中断)信号来自$CPU$外部,与当前执行的命令无关。
|
||||
+ 外设请求:如$I/O$操作完成时发出的中断信号。
|
||||
+ 时钟中断:时间片已到。
|
||||
+ 人工干预。
|
||||
|
||||
另一种分类方式内中断分为:
|
||||
|
||||
+ 陷阱、陷入。
|
||||
+ 故障。
|
||||
+ 终止。
|
||||
|
||||
#### 外中断的处理过程
|
||||
|
||||
1. 关中断。$CPU$响应中断后,首先要保护程序的现场状态,在保护现场的过程中,$CPU$不应响应更高级中断源的中断请求。否则,若现场保存不完整,在中断服务程序结束后,也就不能正确地恢复并继续执行现行程序。
|
||||
2. 保存断点。为保证中断服务程序执行完毕后能正确地返回到原来的程序,必须将原来的程序的断点(即程序计数器$PC$)保存起来。
|
||||
3. 中断服务程序寻址。其实质是取出中断服务程序的入口地址送入程序计数器$PC$。
|
||||
4. 保存现场和屏蔽字。进入中断服务程序后,首先要保存现场,现场信息一般是指程序状态字寄存器PSWR和某些通用寄存器的内容。
|
||||
5. 开中断。允许更高级中断请求得到响应。
|
||||
6. 执行中断服务程序。这是中断请求的目的。
|
||||
7. 关中断。保证在恢复现场和屏蔽字时不被中断。
|
||||
8. 恢复现场和屏蔽字。将现场和屏蔽字恢复到原来的状态。
|
||||
9. 开中断、中断返回。中断服务程序的最后一条指令通常是一条中断返回指令,使其返回到原程序的断点处,以便继续执行原程序。
|
||||
|
||||
第一步道第三步是$CPU$进入中断周期后,由硬件自动完成(中断隐指令),第四到九条是中断服务程序完成。
|
||||
|
||||
### 系统调用
|
||||
|
||||
#### 系统调用的概念
|
||||
|
||||
系统调用是程序接口的组成部分,用于应用软件调用,也称为广义指令。可以认为是一种可供应应用程序调用的特殊函数,应用程序可以发出系统调用请求来获得操作系统的服务。
|
||||
|
||||
#### 系统调用的过程
|
||||
|
||||
为什么要使用系统调用来处理应用程序的请求?如果不同进程争用有限的资源,没有良好的处理机制就会混乱。所以操作系统提供系统调用提供统一处理的过程规范,应用程序通过系统调用发出请求,操作系统在根据请求协调管理。
|
||||
|
||||
系统调用本质就是指令中断,所以需要特权指令,从而系统调用的相关处理只能在**核心态**下进行。
|
||||
|
||||
1. 传递系统调用参数。
|
||||
2. 执行陷入指令(用户态)。
|
||||
3. 执行系统调用相应服务程序(核心态)。
|
||||
4. 返回用户程序。
|
||||
|
||||
+ 陷入指令也称为访管指令,在用户态执行(因此不是特权指令),执行陷入指令后立刻引发一个内中断,从而$CPU$进入核心态。
|
||||
+ 发出系统调用请求的是在用户态,而对系统调用的相应处理在核心态下进行。
|
||||
+ 陷入指令是**唯一一个**只能在用户态执行,而不能核心态执行的指令。
|
||||
|
||||
#### 系统调用的类别
|
||||
|
||||
+ 设备管理:设备的请求、释放、启动。
|
||||
+ 文件管理:文件的读、写、创建、删除。
|
||||
+ 进程管理:进程的创建、撤销、阻塞、唤醒。
|
||||
+ 进程通信:进程之间的消息传递、信号传递。
|
||||
+ 内存管理:内存的分配、回收。
|
||||
|
||||
#### 系统调用与库函数的区别
|
||||
|
||||
层次|使用关系
|
||||
:--:|:-----:
|
||||
普通应用程序|可直接使用系统调用,也可以使用库函数。有的库函数涉及系统调用有些则不涉及
|
||||
编程语言|向上提供库函数,有时会将系统调用封装为库函数以隐藏系统调用细节,从而使上层系统调用更方便
|
||||
操作系统|向上提供系统调用
|
||||
裸机|无
|
||||
|
||||
## 操作系统的体系结构
|
||||
|
||||
体系结构根据内核功能的多少分为:
|
||||
@@ -223,79 +342,3 @@
|
||||
+ 大内核:除了基本功能外还包含进程管理等其他功能。
|
||||
+ 优点:高性能。
|
||||
+ 缺点:内核代码庞大,结构混乱,难以维护。
|
||||
|
||||
## 中断
|
||||
|
||||
中断是内核所必要的基本功能。
|
||||
|
||||
### 中断机制的概念
|
||||
|
||||
+ 并发批处理就需要中断机制。发生中断就表示需要操作系统介入,开展管理工作。
|
||||
+ 用户态道核心态之间的转换是通过中断实现的,且是唯一的途径。
|
||||
+ 而核心态道用户态之间的切换只用执行一个特权指令,将程序状态字PSW的标志位设置为用户态。
|
||||
|
||||
1. 当中断发生时,$CPU$立刻进入核心态。
|
||||
2. 当中断发生后,当前运行的进程暂停,并由操作系统内核对中断进行处理。
|
||||
3. 对于不同的中断信号会进行不同的处理。
|
||||
|
||||
### 中断的分类
|
||||
|
||||
+ 内中断(异常、例外、陷入)信号来自$CPU$内部,与当前执行的命令有关。
|
||||
+ 自愿中断:指令中断。如系统调用时使用的访管指令(陷入指令、trap指令)
|
||||
+ 强迫中断:
|
||||
+ 硬件故障。(缺页)
|
||||
+ 软件中断。(整数除0)
|
||||
+ 外中断(中断)信号来自$CPU$外部,与当前执行的命令无关。
|
||||
+ 外设请求。(I/O操作完成时发出的中断信号)
|
||||
+ 人工干预。
|
||||
|
||||
另一种分类方式内中断分为:
|
||||
|
||||
+ 陷阱、陷入。
|
||||
+ 故障。
|
||||
+ 终止。
|
||||
|
||||
### 外中断的处理过程
|
||||
|
||||
1. 执行外每个指令后,$CPU$都要检查当前是否有外部中断信号。
|
||||
2. 若检测到外部中断信号,则需要保护呗中断进程的$CPU$环境(如程序状态字PSW、程序计数器PC、各种通用寄存器)。
|
||||
3. 根据中断信号类型转入相应的中断处理程序。
|
||||
4. 恢复原进程的$CPU$环境并退出中断,返回原进程继续往下执行。
|
||||
|
||||
## 系统调用
|
||||
|
||||
### 系统调用的概念
|
||||
|
||||
系统调用是程序接口的组成部分,用于应用软件调用,也称为广义指令。可以任务是一种可供应应用程序调用的特殊函数,应用程序可以发出系统调用请求来获得操作系统的服务。
|
||||
|
||||
### 系统调用的过程
|
||||
|
||||
为什么要使用系统调用来处理应用程序的请求?如果不同进程争用有限的资源,没有良好的处理机制就会混乱。所以操作系统提供系统调用提供统一处理的过程规范,应用程序通过系统调用发出请求,操作系统在根据请求协调管理。
|
||||
|
||||
系统调用本质就是指令中断,所以需要特权指令,从而系统调用的相关处理只能在**核心态**下进行。
|
||||
|
||||
1. 传递系统调用参数。
|
||||
2. 执行陷入指令(用户态)。
|
||||
3. 执行系统调用相应服务程序(核心态)。
|
||||
4. 返回用户程序。
|
||||
|
||||
+ 陷入指令在用户态执行,执行陷入指令后立刻引发一个内中断,从而$CPU$进入核心态。
|
||||
+ 发出系统调用请求的是在用户态,而对系统调用的相应处理在核心态下进行。
|
||||
+ 陷入指令是**唯一一个**只能在用户态执行,而不能核心态执行的指令。
|
||||
|
||||
### 系统调用的类别
|
||||
|
||||
+ 设备管理:设备的请求、释放、启动。
|
||||
+ 文件管理:文件的读、写、创建、删除。
|
||||
+ 进程管理:进程的创建、撤销、阻塞、唤醒。
|
||||
+ 进程通信:进程之间的消息传递、信号传递。
|
||||
+ 内存管理:内存的分配、回收。
|
||||
|
||||
### 系统调用与库函数的区别
|
||||
|
||||
层次|使用关系
|
||||
:--:|:-----:
|
||||
普通应用程序|可直接使用系统调用,也可以使用库函数。有的库函数涉及系统调用有些则不涉及
|
||||
编程语言|向上提供库函数,有时会将系统调用封装为库函数以隐藏系统调用细节,从而使上层系统调用更方便
|
||||
操作系统|向上提供系统调用
|
||||
裸机|无
|
||||
|
||||
Reference in New Issue
Block a user