操作系统课程实验1-进程调度模拟实验

操作系统课程实验1-进程调度模拟实验

一、实验介绍

1.1 实验目的

本实验模拟在单处理机环境下的处理机调度,帮助理解进程调度的概念,深入了解进程控制块的功能,以及进程的创建、撤销和进程各个状态间的转换过程。

1.2 实验内容
  1. 进程调度算法:采用最高优先数优先的调度算法、先来先服务算法、SJF和多级反馈调度算法。
  2. 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。进程的优先数及需要的运行时间可以事先人为输入(也可以由随机数产生)。进程的到达时间为进程输入的时间。 进程的运行时间以时间片为单位进行计算。
1.3 实验要求
  1. 每进行一次调度程序都显示输出一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
  2. 对同一组进程的各种调度算法分别计算平均周转时间和平均带权周转时间。
1.4 参考测试数据

系统有5个进程,其就绪时刻、服务时间和优先级(优先级数值越大优先级越高)如下图所示:
在这里插入图片描述

多级反馈队列调度算法:设3个就绪队列,时间片分别为1、2、3。

二、实现代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

typedef struct ProcessControlBlock { // 定义进程控制块结构体
	int name;                   // 进程名称
	unsigned int Arrive_Time;   // 到达时间
	unsigned int Wait_Time;     // 等待时间
	unsigned int Start_Time;    // 开始时间
	unsigned int Serve_Time;    // 服务时间
	unsigned int Finish_Time;   // 完成时间
	int Priority;               // 优先级
	unsigned int cycle_time;    // 周转时间
	double Weighted_cycle_time; // 带权周转时间
	unsigned int Original_Serve_Time;
	bool FinishFlag;            // 完成标志
} PCB;                          // 进程控制块的别名

typedef struct Multilevel_Feedback_Queue { // 定义多级反馈队列
	int L1_Length, L1[5];       // 第一级别反馈队列
	int L2_Length, L2[5];       // 第二级别反馈队列
	int L3_Length, L3[5];       // 第三级别反馈队列
	unsigned int Time_Slice[3]; // 三级反馈队列分配的时间片
} MFQ;



void PCB_Info_Input(PCB Process_HPF[5], PCB Process_FCFS[5], PCB Process_SJF[5], PCB Process_MFQ[5]); 					 	// 函数声明:输入进程控制块信息

void Highest_Prioriy_First(PCB  Process[5]); 	// 函数声明:最高优先级优先算法
void First_Come_First_Serve(PCB Process[5]); 	// 函数声明:先来先服务算法
void Shortest_Job_First(PCB Process[5]);	 	// 函数声明:短作业优先算法
void Multilevel_Feedback_Queue_Algorithm(PCB Process[5]);	// 函数声明:多级反馈队列算法
void Multilevel_Feedback_Queue_Algorithm_Input(MFQ * mfq);	// 函数声明:多级反馈队列的输入

bool SortBy_Priority(PCB* a, PCB* b);		 	// 函数声明:按优先级排序
bool SortBy_ServeTime(PCB* a, PCB* b);		 	// 函数声明:按服务时间排序
bool SortBy_ArriveTime(PCB a, PCB b);		 	// 函数声明:按到达时间排序


int main(void) {
	PCB Process_HPF[5]; 								// 定义5个进程控制块数组
	PCB Process_FCFS[5]; 								// 定义5个进程控制块数组
	PCB Process_SJF[5]; 								// 定义5个进程控制块数组
	PCB Process_MFQ[5]; 								// 定义5个进程控制块数组
	PCB_Info_Input(Process_HPF, Process_FCFS, Process_SJF, Process_MFQ); 								// 调用输入进程控制块信息函数
	Highest_Prioriy_First(Process_HPF); 				// 调用优先级最高优先算法函数
	First_Come_First_Serve(Process_FCFS); 				// 调用先来先服务算法函数
	Shortest_Job_First(Process_SJF);	 				// 调用短作业优先算法函数
	Multilevel_Feedback_Queue_Algorithm(Process_MFQ); 	// 调用多级反馈队列调度算法

	return 0;
}

//	3比较函数,用于sort函数的参数
bool SortBy_ArriveTime(PCB a, PCB b) {
	return a.Arrive_Time < b.Arrive_Time;
}
bool SortBy_Priority(PCB* a, PCB* b) {
	return a->Priority < b->Priority;
}
bool SortBy_ServeTime(PCB* a, PCB* b) {
	return a->Serve_Time < b->Serve_Time;
}


void PCB_Info_Input(PCB Process_HPF[5], PCB Process_FCFS[5], PCB Process_SJF[5], PCB Process_MFQ[5]) {
	cout << "\nPlease input the Process Control Block information\n" << endl;
	for (int i = 0; i < 5; i++) {
		printf("PCB%d:", i);
		scanf("%u%u%d", &Process_HPF[i].Arrive_Time, &Process_HPF[i].Serve_Time, &Process_HPF[i].Priority);
		// 完成输入的深拷贝
		Process_FCFS[i].Arrive_Time = Process_SJF[i].Arrive_Time = Process_MFQ[i].Arrive_Time = Process_HPF[i].Arrive_Time;
		Process_FCFS[i].Serve_Time = Process_SJF[i].Serve_Time = Process_MFQ[i].Serve_Time = Process_HPF[i].Serve_Time;
		Process_FCFS[i].Priority = Process_SJF[i].Priority = Process_MFQ[i].Priority = Process_HPF[i].Priority;

		Process_HPF[i].name = Process_FCFS[i].name = Process_SJF[i].name = Process_MFQ[i].name = i + 1; 							// 设置进程名称
		Process_HPF[i].FinishFlag = Process_FCFS[i].FinishFlag = Process_SJF[i].FinishFlag = Process_MFQ[i].FinishFlag = false; 	// 初始化完成标志为false
	}
}

// 优先级最高优先调度算法函数
void Highest_Prioriy_First(PCB Process[5]) {

	cout << "\n优先级最高优先调度算法:" << endl;
	PCB* Available_Processes[5]; 	// 定义指向进程控制块的指针数组
	int FinishCout = 0; 			// 完成进程计数器初始化为0
	unsigned Time = 0; 				// 时间初始化为0
	cout << endl;

	sort(Process, Process + 5, SortBy_ArriveTime);  // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { 						// 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = 0; 									// 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { 				// 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) { // 如果进程已到达且未完成
				Available_Processes[j++] = Process + i; 							 // 将该进程加入到可用进程数组中
			}
		}

		// 如果j为0,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == 0) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 将当前时间已经到达的所有进程按优先级进行排序
		sort(Available_Processes, Available_Processes + j, SortBy_Priority);
		// 选取优先级最大的进程执行任务
		Available_Processes[0]->Start_Time = Time; 	// 设置进程开始时间
		Available_Processes[0]->Wait_Time = Available_Processes[0]->Arrive_Time; // 设置进程等待时间
		Time += Available_Processes[0]->Serve_Time; // 更新时间
		Available_Processes[0]->Finish_Time = Time; // 设置进程完成时间
		Available_Processes[0]->cycle_time = Available_Processes[0]->Finish_Time - Available_Processes[0]->Arrive_Time; 	// 计算进程周转时间
		Available_Processes[0]->Weighted_cycle_time = Available_Processes[0]->cycle_time * 1.0 / Available_Processes[0]->Serve_Time;
		Available_Processes[0]->FinishFlag = true; 	// 设置进程完成标志为true
		cout << "PCB:" << Available_Processes[0]->name << "\tArriveTime:" << Available_Processes[0]->Arrive_Time
		     << "\tPriority:" << Available_Processes[0]->Priority
		     << "\tWaitTime:" << Available_Processes[0]->Wait_Time
		     << "\tStartTime:" << Available_Processes[0]->Start_Time
		     << "\tServeTime:" << Available_Processes[0]->Serve_Time
		     << "\tFinishTime:" << Available_Processes[0]->Finish_Time
		     << "\tCircleTime:" << Available_Processes[0]->cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; 							// 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间
}

// 先来先服务调度算法(FCFS)
void First_Come_First_Serve(PCB  Process[5]) {

	cout << "\n先来先服务调度算法:" << endl;
	int FinishCout = 0; 	// 完成进程计数器初始化为0
	unsigned Time = 0; 		// 时间初始化为0
	cout << endl;
	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { // 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = -1; 		 // 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { // 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) {
				j = i;
				break;
			}
		}
		// 如果j为-1,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == -1) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 选取当前满足条件且到达时间最早的进程进行执行
		Process[j].Start_Time = Time; 	// 设置进程开始时间
		Process[j].Wait_Time = Process[j].Start_Time - Process[j].Arrive_Time; // 设置进程等待时间
		Time += Process[j].Serve_Time; 	// 更新时间
		Process[j].Finish_Time = Time; 	// 设置进程完成时间
		Process[j].cycle_time = Process[j].Finish_Time - Process[j].Arrive_Time; 				// 计算进程周转时间
		Process[j].Weighted_cycle_time = Process[j].cycle_time * 1.0 / Process[j].Serve_Time;
		Process[j].FinishFlag = true; 	// 设置进程完成标志为true

		cout << "PCB:" << Process[j].name << "\tArriveTime:" << Process[j].Arrive_Time
		     << "\tWaitTime:" << Process[j].Wait_Time
		     << "\tStartTime:" << Process[j].Start_Time
		     << "\tServeTime:" << Process[j].Serve_Time
		     << "\tFinishTime:" << Process[j].Finish_Time
		     << "\tCircleTime:" << Process[j].cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; // 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间
}

// 短作业优先算法 (SJF)
void Shortest_Job_First(PCB Process[5]) {

	cout << "\n短作业优先算法:" << endl;
	PCB* Available_Processes[5]; 	// 定义指向进程控制块的指针数组
	int FinishCout = 0; 			// 完成进程计数器初始化为0
	unsigned Time = 0; 				// 时间初始化为0
	cout << endl;

	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { 	// 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = 0; 				// 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { // 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) { 	// 如果进程已到达且未完成
				Available_Processes[j++] = Process + i; 								// 将该进程加入到可用进程数组中
			}
		}

		// 如果j为0,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == 0) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 将当前时间已经到达的所有进程按服务时间进行排序
		sort(Available_Processes, Available_Processes + j, SortBy_ServeTime);
		// 选取当前满足条件且服务时间最短的进程执行任务
		Available_Processes[0]->Start_Time = Time; 	// 设置进程开始时间
		Available_Processes[0]->Wait_Time = Available_Processes[0]->Arrive_Time; // 设置进程等待时间
		Time += Available_Processes[0]->Serve_Time; // 更新时间
		Available_Processes[0]->Finish_Time = Time; // 设置进程完成时间
		Available_Processes[0]->cycle_time = Available_Processes[0]->Finish_Time - Available_Processes[0]->Arrive_Time; 	// 计算进程周转时间
		Available_Processes[0]->Weighted_cycle_time = Available_Processes[0]->cycle_time * 1.0 / Available_Processes[0]->Serve_Time;
		Available_Processes[0]->FinishFlag = true; 	// 设置进程完成标志为true
		cout << "PCB:" << Available_Processes[0]->name << "\tArriveTime:" << Available_Processes[0]->Arrive_Time
		     << "\tWaitTime:" << Available_Processes[0]->Wait_Time
		     << "\tStartTime:" << Available_Processes[0]->Start_Time
		     << "\tServeTime:" << Available_Processes[0]->Serve_Time
		     << "\tFinishTime:" << Available_Processes[0]->Finish_Time
		     << "\tCircleTime:" << Available_Processes[0]->cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; 							// 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间

}

void Multilevel_Feedback_Queue_Algorithm(PCB Process[5]) {
	cout << "\n多级反馈队列调度算法:" << endl;
	MFQ MFQSet;
	Multilevel_Feedback_Queue_Algorithm_Input(&MFQSet); // 调用输入多级反馈队列的函数
	queue<PCB> L1, L2, L3; // 定义三个队列
	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	unsigned int Time = 0; // 时间初始化为0
	double avg = 0, weighted_avg = 0; // 初始化平均周转时间和带权平均周转时间
	for (int i = 0; i < 5; i++) { // 将进程按照到达时间加入到第一级别队列
		Process[i].Original_Serve_Time = Process[i].Serve_Time;
		L1.push(Process[i]);

	}
	while (!L1.empty() || !L2.empty() || !L3.empty()) { // 当三个队列有不为空的时循环
		cout << "Time:" << Time << " \t\t"; // 输出当前时间
		if (!L1.empty()) { // 如果第一级别队列不为空
			PCB temp = L1.front(); // 获取队首进程
			L1.pop();              // 弹出队首进程
			cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
			Time += min(temp.Serve_Time, MFQSet.Time_Slice[0]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
			temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[0])); // 更新当前进程的服务时间
			if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
				temp.Finish_Time = Time; // 设置当前进程的完成时间
				temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
				temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
				avg += temp.cycle_time;     // 计算总周转时间
				weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
				cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
			} else {
				cout << 'P' << temp.name << "转移到队列2的末尾\n";
				L2.push(temp); // 否则将当前进程加入到第二级别队列
			}
		} else if (!L2.empty()) { // 如果第一级别队列为空但第二级别队列不为空
			PCB temp = L2.front(); // 获取队首进程
			L2.pop();              // 弹出队首进程
			cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
			Time += min(temp.Serve_Time, MFQSet.Time_Slice[1]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
			temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[1])); // 更新当前进程的服务时间
			if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
				temp.Finish_Time = Time; // 设置当前进程的完成时间
				temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
				temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
				avg += temp.cycle_time;     // 计算总周转时间
				weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
				cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
			} else {
				cout << 'P' << temp.name << "转移到队列3的末尾\n";
				L3.push(temp); // 否则将当前进程加入到第三级别队列
			}
		} else { // 如果第一级别和第二级别队列均为空
			while (!L3.empty()) {
				PCB temp = L3.front(); // 获取队首进程
				L3.pop();              // 弹出队首进程
				cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
				Time += min(temp.Serve_Time, MFQSet.Time_Slice[2]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
				temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[2])); // 更新当前进程的服务时间
				if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
					temp.Finish_Time = Time; // 设置当前进程的完成时间
					temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
					temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
					avg += temp.cycle_time;     // 计算总周转时间
					weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
					cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
				} else {
					cout << 'P' << temp.name << "继续执行\n";
					L3.push(temp); // 将当前进程加入到第三级别队列末尾
				}
			}
		}
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转
}



// 输入多级反馈队列的函数
void Multilevel_Feedback_Queue_Algorithm_Input(MFQ *mfq) {
	cout << "Please input the Time Slice(Three Numbers) for Multilevel Feedback Queue" << endl;
	cin >> mfq->Time_Slice[0] >> mfq->Time_Slice[1] >> mfq->Time_Slice[2];
}

三、心灵的救赎

  1. “爱”就是科学与逻辑永远无法解释的程序
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/651552.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

md是什么?如何打开md类型的文件?假如使用Typora打开,如何免费激活Typora?

md是什么&#xff1f;如何打开md类型的文件 前言一、md是什么简介常见打开md类型文件的方法使用文本编辑器使用专用Markdown编辑器使用在线Markdown编辑器在浏览器中安装插件打开 二、下载安装Typora三、免费激活Typora激活Typora关闭软件每次启动时的已激活弹窗去除软件左下角…

动手学深度学习4.6 暂退法-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;丢弃法_哔哩哔哩_bilibili 本节教材地址&#xff1a;4.6. 暂退法&#xff08;Dropout&#xff09;…

NDIS驱动程序堆栈

NDIS 6.0 引入了暂停和重启驱动程序堆栈的功能。 若要支持 NDIS 6.0 提供的堆栈管理功能&#xff0c;必须重写旧版驱动程序。 NDIS 6.0 还引入了 NDIS Filter驱动程序。 Filter驱动程序可以监视和修改协议驱动程序与微型端口驱动程序之间的交互。 与 NDIS 5 相比&#xff0c;F…

188M2传奇BLUEM2引擎源码开源版附带编译教程2024最新开源

2024最新开源188M2传奇BLUEM2引擎源码开源2版最初开源版本附带编译教程 源码下载地址&#xff1a;极速云 如果需要优惠可以选择第一版最初开源188M2传奇BLUEM2引擎源码开源1版最初开源版本附带编译教程2024最新开源

vue2的方法与监听

vue2的方法 不可以使用箭头函数 <template> <div><div>{{sum2()}}</div><button click"add">add</button> </div></template><script> export default {data(){return{name:"张三",num:20,num2:3…

AI分析SP和pk进行sk分析

SP原始表行标题代表题目序号&#xff0c;列代表学生&#xff0c;如果学生答对题目为1&#xff0c;否则为0。问题知识点矩阵这个文件横轴代表每个知识点&#xff0c;列标题代表每个题目序号&#xff0c;如果题目包含这个知识点则该处值为1。通过两个文件判断学生对于每个知识点的…

达梦数据库创建根据日期按月自动分区表

达梦数据库创建根据日期自动分区表 概念 达梦数据交换平台(简称DMETL)是在总结了众多大数据项目经验和需求并结合最新大数据发展趋势和技术的基础上&#xff0c;自主研发的通用的大数据处理与集成平台。 DMETL创新地将传统的ETL工具&#xff08;Extract、Transform、Loading…

计算机网络6——应用层6

文章目录 一、应用进程跨越网络的通信1、系统调用和应用编程接口2、几种常用的系统调用1&#xff09;连接建立阶段2&#xff09;数据传送阶段3&#xff09;连接释放阶段 二、P2P 应用1、具有集中目录服务器的P2P工作方式2、具有全分布式结构的P2P文件共享程序3、P2P 文件分发的…

Android 通过布局生成图片

通过布局生成图片 首先效果图 在竖屏的情况下通过&#xff0c;一般情况下&#xff0c;只要布局在页面上可见&#xff0c;并显示全&#xff0c;通过布局生成图片&#xff0c;都可以&#xff0c;但是横屏就不行了&#xff0c;会出现图片显示不完全的情况。 val bitmap Bitmap.c…

APM2.8用USB在线下载固件

1.把APM飞控用安卓手机的USB线插入电脑。 选择COM口&#xff0c;不要选择auto&#xff0c;如果你没有COM口说明你驱动安装有问题。 波特率115200。点击相应的图标就可以下载固件到飞控板。 请注意&#xff1a;烧录APM必须选择INSTALL FIRMWARE LEAGACY,第一个是用于刷pixhawk的…

sqpserver——利用scott库练习内连接(一)

一.查找每个员工的姓名&#xff0c;部门编号&#xff0c;薪水和薪水等级 select emp.ename, emp.deptno, emp.sal, SALGRADE.GRADE from emp join SALGRADE on emp.sal>LOSAL and emp.sal<HISAL; 二.查找每个部门的编号&#xf…

Cocos Creator 安卓环境配置

系统&#xff1a;Win10&#xff0c;引擎版本&#xff1a;CocosCreator3.8.2&#xff0c; 时间&#xff1a;2024.05.23 安装 Java SDK(JDK)下载地址 注意&#xff1a;Java版本对应的Gradle: 详见表 Table 1. Java Compatibility 此处选择 Java 21 对应 Gradle 8.5 配置Java系统…

【全开源】景区手绘地图导览系统源码(ThinkPHP+FastAdmin)

一款基于ThinkPHPFastAdmin开发多地图手绘地图导览系统(仅支持H5)&#xff0c;景区升4A5A必备系统&#xff0c;高级版支持全景。 ​打造个性化游览新体验 一、引言&#xff1a;景区导览系统的革新 在旅游业蓬勃发展的今天&#xff0c;景区导览系统成为了提升游客体验的关键。…

强化学习——学习笔记

一、什么是强化学习&#xff1f; 强化学习 (Reinforcement Learning, RL) 是一种通过与环境交互来学习决策策略的机器学习方法。它的核心思想是让智能体 (Agent) 在执行动作 (Action)、观察环境 (Environment) 反馈的状态 (State) 和奖励 (Reward) 的过程中&#xff0c;学习到…

三维大场景管理-3Dtiles规范

简介 &#xff1a; 这篇文章都是三年前写的了&#xff0c;一直在笔记库存中&#xff0c;今天把他放出来。主要是讲Cesium 的3Dtiles 格式&#xff0c;当然3Dtiles主要是解决场景管理大场景的LOD实现的问题&#xff0c;不管是剔除渲染性能优化之Culling 剔除或者 LOD 、3Dtiles…

安装HAP时提示“code:9568344 error: install parse profile prop check error”错误

问题现象 在启动调试或运行应用/服务时&#xff0c;安装HAP出现错误&#xff0c;提示“error: install parse profile prop check error”错误信息。 解决措施 该问题可能是由于应用使用了应用特权&#xff0c;但应用的签名文件发生变化后未将新的签名指纹重新配置到设备的特…

使用 Spring Cloud Alibaba AI 构建 RAG 应用

作者&#xff1a;姬世文 背景介绍 RAG&#xff08;Retrieval Augmented Generation&#xff09; 检索增强生成&#xff08;RAG&#xff09;是一种用于将数据与人工智能模型集成的技术。在 RAG 工作流程中&#xff0c;第一步将文档数据加载到矢量数据库&#xff08;例如 Redi…

ssm145基于java的电脑硬件库存管理系统+jsp

电脑硬件库存管理系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对电脑硬件库存信息管理混乱&…

YOLOv8+PyQt5车辆类型检测系统完整资源集合(yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)

资源包含可视化的车辆类型检测系统&#xff0c;基于最新的YOLOv8训练的车辆类型检测模型&#xff0c;和基于PyQt5制作的可视化车辆类型检测系统&#xff0c;包含登陆页面、注册页面和检测页面&#xff0c;该系统可自动检测和识别图片或视频当中出现的21种车辆类型&#xff0c;包…

初级爬虫的总结一

初级爬虫的总结一之百度网页爬虫 一、寻找正确的sugrec二、url拼接出问题&#xff0c;解决办法 我遇到的问题&#xff1a; 1、没有找对网页sugrec&#xff0c;导致connect-type没有找对&#xff0c;以及一些小问题 2、url拼接时候出现乱码 一、寻找正确的sugrec 1、打开百度网…