进程的调度算法. tast_struct 僵尸进程/孤儿进程

本文介绍了六种常见的进程调度算法:先来先服务、短作业优先、优先级调度、高响应比优先、轮转调度和多级反馈队列,并讨论了它们各自的优缺点及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**

首先来看下集中常见的进程调度算法:

**
这里写图片描述
(1)先来先服务调度算法
——如果早就绪的进程排在就绪队列的前面,迟就绪的进程排在就绪队列的后面,那么先来先服务(FCFS: first come first service)总是把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的下一个CPU周期的长短及其他因素。FCFS算法简单易行,是一种非抢占式策略,但性能却不大好。

——先来先服务的调度算法:最简单的调度算法,既可以用于作业调度 ,也可以用于程序调度,当作业调度中采用该算法时,系统将按照作业到达的先后次序来进行调度,优先从后备队列中,选择一个或多个位于队列头部的作业,把他们调入内存,分配所需资源、创建进程,然后放入“就绪队列”,直到该进程运行到完成或发生某事件堵塞后,进程调度程序才将处理机分配给其他进程。

——优缺点:有利于长作业(进程)而不利于短作业(进程)
有利于CPU繁忙型作业(进程)而不利于I/O繁忙型作业(进程)
网上代码:https://wenku.baidu.com/view/2891e013cc22bcd127ff0c12.html

(2)短作业优先调度算法
——定义:对预计执行时间短的作业(进程)优先分派处理机。通常后来的短作业不抢先正在执行的作业。

——短作业优先算法的特点
@ 优点:比FCFS改善平均周转时间和平均带权周转时间,缩短作业的等待时间;提高系统的吞吐量;
@ 缺点:对长作业非常不利,可能长时间得不到执行;未能依据作业的紧迫程度来划分执行的优先级;难以准确估计作业(进程)的执行时间,从而影响调度性能。
网上代码:https://wenku.baidu.com/view/498aae92524de518964b7dc4.html

(3)优先级调度算法
优先级调度算法,即给每个作业一个优先级,优先级越高越紧迫,应该先执行。
进程优先数的设置可以是动态的也可以是静态的;最高优先数算法又可与不同的CPU方式结合起来,形成可抢占最高优先级算法和不可抢占式最高优先级算法。
显然:可抢占式最高优先级算法更严格的反映了优先级的特征,实现了使优先级进程尽可能快的完成其任务目标,从而获得了良好的服务质量,但无疑的增加了系统的开销。

(4)高响应比优先调度算法
高响应比优先调度算法(Highest Response Ratio Next)是一种对CPU中央控制器响应比的分配的一种算法。HRRN是介于FCFS(先来先服务算法)与SJF(短作业优先算法)之间的折中算法,既考虑作业等待时间又考虑作业运行时间,既照顾短作业又不使长作业等待时间过长,改进了调度性能。
基本思想:高响应比优先调度算法的基本思想是把CPU分配给就绪队列中响应比最高的进程。
这里写图片描述
短作业优先调度算法 + 动态优先权机制;既考虑作业的执行时间也考虑作业的等待时间,综合 了先来先服务和最短作业优先两种算法的特点。
优缺点:短作业与先后次序的兼顾,且不会使长作业长期得不到服务;
响应比计算系统开销,增加系统开销。
(5)轮转调度算法
时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾。
基本原理:在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则,排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片.时间片的大小从几ms到几百ms.当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片.这样就可以保证就绪队列中的所有进程,在一给定的时间内,均能获得一时间片的处理机执行时间.

(6)多级反馈队列
——设置多个就绪队列,并为各个队列赋予不同的优先级. 第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低.该算法赋予各个队列中进程执行时间片的大小也各不相同:
在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小.
例如:第二个队列的时间片要比第一个队列的时间片长一倍,……,第i+1个队列的时间片要比第i个队列的时间片长一倍.
这里写图片描述
——当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度.当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n队列中便采取按时间片轮转的方式运行.

—— 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行; 仅当第1~(i-1) 队列均空时,才会调度第i队列中的进程运行.如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程.?
性能
终端型作业用户
短批处理作业用户
长批处理作业用户
满足了多数用户的需求

这里写图片描述

————————————————————————————————————
关于tast_struct结构体中的各个字段的含义
这里写图片描述
http://blog.youkuaiyun.com/Paranoid_cc/article/details/79463717

————————————————————————————————————-
僵尸进程和孤儿进程


点我 http://blog.youkuaiyun.com/Paranoid_cc/article/details/79473260


``` #include <ros/ros.h> #include <geometry_msgs/PoseStamped.h> // 引入位姿消息类型 #include <geometry_msgs/Twist.h> // 引入速度消息类型 #include <mavros_msgs/CommandBool.h> // 引入指令消息类型 #include <mavros_msgs/SetMode.h> // 引入设置模式消息类型 #include <mavros_msgs/State.h> // 引入状态消息类型 #include <std_msgs/String.h> // 引入字符串消息类型 #include <cmath> // 添加cmath头文件以使用sqrt函数 #include <ce_msgs/missionstate.h> // 引入自定义消息类型 #include <pid.h> // 需要实现PID控制器 #include <tf/transform_datatypes.h> // 用于姿态转换 void yolov5_camera_callback(std_msgs::String msg) { ROS_INFO(msg.data.c_str()); // 解析目标中心坐标(示例格式:"x:0.5,y:0.3") std::string data = msg->data; size_t x_pos = data.find("x:"); size_t y_pos = data.find("y:"); if(x_pos != std::string::npos && y_pos != std::string::npos) { target_center.x = std::stof(data.substr(x_pos+2, y_pos-x_pos-3)); target_center.y = std::stof(data.substr(y_pos+2)); target_center.z = 0; // 假设二维检测 } } void mavros_pose_callback(geometry_msgs::PoseStamped msg) { ROS_INFO("Current state: %d", msg.mode); } void visual_servo_control() { geometry_msgs::Twist cmd_vel; // 计算位置误差(需根据相机坐标系转换) double error_x = target_center.x - current_pose.pose.position.x; double error_y = target_center.y - current_pose.pose.position.y; // PID计算 cmd_vel.linear.x = pid_x.calculate(error_x); cmd_vel.linear.y = pid_y.calculate(error_y); cmd_vel.linear.z = pid_z.calculate(0); // 保持高度 // 发布速度指令 cmd_vel_pub.publish(cmd_vel); // 检查终止条件 if(sqrt(error_x*error_x + error_y*error_y) < 0.1) { // 阈值0.1米 ce_msgs::missionstate end_msg; end_msg.state = "ending"; mission_end_pub.publish(end_msg); current_state = FINISHED; } } int main(int argc, char *argv[]) { ros::init(argc, argv, "cuadc_mavros_state"); ros::NodeHandle nh; ros::Subscriber mission_state_sub = nh.subscribe<std_msgs::String>("yolov5_camera", 10, yolov5_camera_callback); ros::Subscriber mavros_state_sub = nh.subscribe<geometry_msgs::PoseStamped>("/mavros/local_position/pose", 10, mavros_pose_callback); cmd_vel_pub = nh.advertise<geometry_msgs::Twist>("/mavros/setpoint_velocity/cmd_vel_unstamped", 10); mission_end_pub = nh.advertise<ce_msgs::missionstate>("tast_end", 10); // PID初始化(需根据实际调试) pid_x.init(0.5, 0.01, 0.05); // KP, KI, KD pid_y.init(0.5, 0.01, 0.05); pid_z.init(0.2, 0.0, 0.0); ros::Rate rate(20); // 20Hz while (ros::ok()) { switch(current_state) { case HOVERING: if(check_hover_stable()) { // 需要实现悬停检测 current_state = VISUAL_SERVOING; } break; case VISUAL_SERVOING: visual_servo_control(); break; case FINISHED: ROS_INFO("Mission completed"); return 0; } ros::sleep(); ros::spinOnce(); } return 0; }```/home/gtc/catkin_ws/src/task_pkg/src/cuadc_mavros_state.cpp:10:10: fatal error: pid.h: 没有那个文件或目录 10 | #include <pid.h> // 需要实现PID控制器 加入代码之后编译出现这个错误
最新发布
04-02
<think>好的,我现在需要帮用户解决编译错误的问题。用户提供的代码中出现了“pid.h: 没有那个文件或目录”的错误,这说明编译器找不到这个头文件。首先,我得分析可能的原因。 首先,用户可能在代码中引用了PID控制器库,但实际项目里并没有这个库。查看代码,确实有#include <pid.h>,而用户可能没有安装或正确包含这个库。常见的PID库可能有多种,比如ROS自有的control_toolbox,或者是用户自己实现的PID类。 接下来,用户可能在代码中使用了PID控制器,但对应的头文件没有正确放置。例如,如果用户自己编写了pid.h,那么这个文件应该放在项目的include目录下,或者在编译时指定了包含路径。如果路径不对,编译器就无法找到。 然后,我需要考虑解决方案。有两种可能性:一种是安装现有的PID库,另一种是用户自己实现PID类。根据代码中的初始化方式(pid_x.init(0.5, 0.01, 0.05);),看起来用户可能期望一个PID类有init方法,接收三个参数。所以可能需要用户自己实现这个类,因为标准的库可能接口不同。 另外,用户可能没有正确配置CMakeLists.txt文件,导致编译器找不到自定义的pid.h。需要检查CMakeLists中的include_directories是否包含头文件所在目录。 现在,我应该建议用户先检查是否存在pid.h文件。如果没有,需要创建。如果有,检查路径是否正确。然后提供简单的PID类实现示例,并指导如何包含到项目中。同时提醒用户修改CMakeLists,确保头文件被正确包含。 此外,用户代码中可能还有其他问题,比如全局变量未声明(如pid_x, pid_y, pid_z,current_pose等),需要指出这些潜在问题,帮助用户全面修正代码。</think>这个错误提示说明编译器找不到`pid.h`头文件。以下是分步解决方案: $$ \text{错误类型} = \begin{cases} \text{头文件路径错误}\\ \text{PID库未安装}\\ \text{自定义头文件未创建} \end{cases} $$ 一、解决方案步骤: 1. **确认PID库存在性** - 检查`/usr/include`或`/usr/local/include`目录下是否存在`pid.h` - 如果使用ROS的control_toolbox,应改为: ```cpp #include <control_toolbox/pid.h> ``` 2. **创建自定义PID类(推荐方案)** ```cpp // 在项目include目录下创建pid.h class PID { public: void init(double Kp, double Ki, double Kd) { kp = Kp; ki = Ki; kd = Kd; integral = 0; prev_error = 0; } double calculate(double error) { integral += error; double derivative = error - prev_error; prev_error = error; return kp*error + ki*integral + kd*derivative; } private: double kp, ki, kd; double integral; double prev_error; }; ``` 3. **修改CMakeLists.txt** ```cmake include_directories( ${catkin_INCLUDE_DIRS} include # 添加自定义头文件路径 ) ``` 4. **全局变量声明(需补充)** ```cpp // 在全局作用域添加 PID pid_x, pid_y, pid_z; geometry_msgs::Point target_center; geometry_msgs::PoseStamped current_pose; ``` 二、潜在问题修复建议: 1. **回调函数修正**: ```cpp // 原代码中msg应为指针类型,修正为: void yolov5_camera_callback(const std_msgs::String::ConstPtr& msg) ``` 2. **坐标系转换**: $$ \begin{cases} \text{相机坐标系到机体坐标系的转换}\\ \text{需使用tf库进行坐标变换}\\ \text{建议添加姿态补偿计算} \end{cases} $$ 三、代码优化建议: 1. 使用ROS参数服务器动态配置PID参数 ```cpp nh.param("pid_x/p", kp, 0.5); ``` 2. 添加异常处理: ```cpp try { target_center.x = std::stof(...); } catch (const std::invalid_argument& e) { ROS_ERROR("解析坐标失败"); } ``` 完成以上修改后,建议按以下流程验证: $$ \text{编译流程} = \text{catkin\_make} \rightarrow \text{source devel/setup.bash} \rightarrow \text{rosrun 节点测试} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值