0%

网络安全技术学习,承认自己的弱点不是丑事。只有对原理了然于心,才能突破更多的限制。拥有快速学习能力的安全研究员,是不能有短板的,有的只能是大量的标准板和几块长板。知识面,决定看到的攻击面有多广;知识链,决定发动的杀伤链有多深。

阅读全文 »

笔记哥讲的挺好的,建议大家都可以去b站上搜索"红队笔记",这台机器也是我放寒假来做的五台机器里强度最高的

阅读全文 »

由MazeSec推出的系列靶机,我会持续更新的(一周最多更新两个,用于戒除自身爱玩欢乐斗地主的不良习性)

阅读全文 »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <stdio.h>

#define NUM_TASKS 5
#define MEMORY_CAPACITY 100 // 用户可用主存(K)
#define TAPE_CAPACITY 4 // 磁带机台数

typedef struct {
const char* name;
int nArrivalTime; // 到达时刻(从 00:00 起的分钟)
int nServiceTime; // 运行时间(分钟)
int nMemoryNeed; // 主存需求
int nTapesNeed; // 磁带机需求(台)

int nAdmittedTime; // 进入系统(分到内存+磁带)时刻;-1 表示尚未进入
int nStartTime; // 获得CPU的时刻
int nFinishTime; // 完成时刻
} Task;

/*
返回t之后的下一次到达时刻;若不存在返回 -1
*/
int NextArrivalTimeAfter(const Task tasks[], int n, int t)
{
int nNextTime = -1;
for (int i = 0; i < n; ++i)
{
if (tasks[i].nAdmittedTime == -1 && tasks[i].nArrivalTime > t)
{
if (nNextTime == -1 || tasks[i].nArrivalTime < nNextTime)
{
nNextTime = tasks[i].nArrivalTime;
}
}
}
return nNextTime;
}

/* 在当前时刻 nCurrentTime,尽可能让已到达的作业进入系统(分配内存和磁带)
- 主存可变分区且允许紧凑:只需比较“剩余总内存”是否足够
- 磁带机静态分配:进入系统后一直占用到完成为止
进入系统的作业按 FCFS 顺序入就绪队列。*/
void AdmitArrivedTasks(
Task tasks[], int n, int nCurrentTime,
int* nFreeMemory, int* nFreeTapes,
int ReadyQueue[], int* nReadyTail)
{
for (int i = 0; i < n; ++i)
{
if (tasks[i].nAdmittedTime == -1 && tasks[i].nArrivalTime <= nCurrentTime)
{
if (tasks[i].nMemoryNeed <= *nFreeMemory &&
tasks[i].nTapesNeed <= *nFreeTapes)
{
*nFreeMemory -= tasks[i].nMemoryNeed; // 占用资源
*nFreeTapes -= tasks[i].nTapesNeed;
tasks[i].nAdmittedTime = nCurrentTime;
ReadyQueue[(*nReadyTail)++] = i; // 进入就绪队列
}
}
}
}

void PrintTime(int nMinutes)
{
printf("%02d:%02d", nMinutes / 60, nMinutes % 60);
}

int main(void)
{
Task tasks[NUM_TASKS] =
{
{"JOB1", 10 * 60 + 0, 40, 35, 3, -1, -1, -1},
{"JOB2", 10 * 60 + 10, 30, 70, 1, -1, -1, -1},
{"JOB3", 10 * 60 + 15, 20, 50, 3, -1, -1, -1},
{"JOB4", 10 * 60 + 35, 10, 25, 2, -1, -1, -1},
{"JOB5", 10 * 60 + 40, 5, 20, 2, -1, -1, -1},
};

int nFreeMemory = MEMORY_CAPACITY;
int nFreeTapes = TAPE_CAPACITY;

int ReadyQueue[NUM_TASKS]; // 就绪队列
int nReadyHead = 0;
int nReadyTail = 0;

int nExecutionOrder[NUM_TASKS]; // CPU 实际执行顺序
int nExecutionCount = 0;

int nRemainingTasks = NUM_TASKS;
int nCurrentTime = -1;
int nRunningTask = -1; // 当前在CPU上的作业索引,-1表示空闲
int nPlannedFinishTime = 0;

while (nRemainingTasks > 0)
{
// 若 CPU 空闲且就绪队列也空,则时间推进到“下一次到达”
if (nRunningTask == -1 && nReadyHead == nReadyTail)
{
int nNextArrivalTime = NextArrivalTimeAfter(tasks, NUM_TASKS, nCurrentTime);
nCurrentTime = nNextArrivalTime;
AdmitArrivedTasks(tasks, NUM_TASKS, nCurrentTime,
&nFreeMemory, &nFreeTapes,
ReadyQueue, &nReadyTail);
}

// 有就绪作业则按FCFS取队头运行
if (nRunningTask == -1 && nReadyHead != nReadyTail)
{
int nTaskId = ReadyQueue[nReadyHead++];
tasks[nTaskId].nStartTime = nCurrentTime;
tasks[nTaskId].nFinishTime = nCurrentTime + tasks[nTaskId].nServiceTime;
nRunningTask = nTaskId;
nPlannedFinishTime = tasks[nTaskId].nFinishTime;
nExecutionOrder[nExecutionCount++] = nTaskId;
}

// 到达与完成事件处理
if (nRunningTask != -1)
{
int nNextArrivalTime = NextArrivalTimeAfter(tasks, NUM_TASKS, nCurrentTime); // nCurrentTime返回下一个JOB
// 遍历在当前JOB结束之前是否有后续JOB满足条件
if (nNextArrivalTime != -1 && nNextArrivalTime <= nPlannedFinishTime)
{
// 运行期间有新作业到达,尝试装入
nCurrentTime = nNextArrivalTime;
AdmitArrivedTasks(tasks, NUM_TASKS, nCurrentTime,
&nFreeMemory, &nFreeTapes,
ReadyQueue, &nReadyTail);
continue; // 再找
}

// 作业完成
nCurrentTime = nPlannedFinishTime;
tasks[nRunningTask].nFinishTime = nCurrentTime;

// 释放资源
nFreeMemory += tasks[nRunningTask].nMemoryNeed;
nFreeTapes += tasks[nRunningTask].nTapesNeed;

nRunningTask = -1; // CPU恢复空闲
nRemainingTasks--;

// 作业完成后可能使等待作业得以装入
AdmitArrivedTasks(tasks, NUM_TASKS, nCurrentTime,
&nFreeMemory, &nFreeTapes,
ReadyQueue, &nReadyTail);
}
}

// 输出执行顺序
printf("作业执行顺序: ");
for (int i = 0; i < nExecutionCount; ++i)
{
printf("%s%s", tasks[nExecutionOrder[i]].name,
(i + 1 < nExecutionCount ? " " : ""));
}
printf("\n");

// 输出每个作业的到达—完成、周转与带权周转
for (int i = 0; i < NUM_TASKS; ++i)
{
int nTurnaround = tasks[i].nFinishTime - tasks[i].nArrivalTime;
double weighted = (double)nTurnaround / tasks[i].nServiceTime;
printf("%s:", tasks[i].name);
PrintTime(tasks[i].nArrivalTime);
printf("");
PrintTime(tasks[i].nFinishTime);
printf("周转时间:%d 带权周转时间:%.2f\n", nTurnaround, weighted);
}

return 0;
}–
/*
在本题我们使用了队列与贪心算法
1. 维护一个就绪队列(ReadyQueue),按实际被系统接受(资源足够)进入队列的顺序
2. 使用贪心算法,表现在谁先到、且资源够,就立即进入系统

就绪队列用于记录已经成功进入系统的作业(即内存和磁带机资源均满足要求)
模拟执行:
JOB1(35,3)运行期间剩余(65,1)没有任何新作业能进入就绪队列
JOB1释放后,剩余(100,4)
JOB2(70,1)运行期间剩余(30,3),JOB4(25,2)进入就绪队列,剩余(5,1),此时没有任何新作业能进入就绪队列
JOB2释放后,剩余(75,2)
JOB4(25,2)运行期间剩余(75,2),JOB5(20,2)进入就绪队列,剩余(55,0),没有任何新作业能进入就绪队列
JOB4释放后,剩余(80,2),JOB3(50,3)无法进入队列
JOB5释放后,剩余(100,4),JOB3进入队列
JOB3执行
结束
*/