2.25作业

文章介绍了如何在C语言中处理SIGINT、SIGCHLD和SIGALRM信号,并展示了使用消息队列进行父子进程间通信的示例,包括发送和接收消息的过程。
处理普通信号:
#include<myhead.h>
void handler(int signo)
{
	if(signo==SIGINT)
	{
		printf("用户按下了CTRL + C\n");
	}
}
int main(int argc, const char *argv[])
{
	/*忽略
	if(signal(SIGINT,SIG_IGN)==SIG_ERR)
	{
		perror("signal error");
		return -1;
   }*/
	/*不忽略
	if(signal(SIGINT,SIG_DFL)==SIG_ERR)
	{
		perror("signal error");
		return -1;
   }*/
	//捕获
	if(signal(SIGINT,handler)==SIG_ERR)
	{
		perror("signal error");
		return -1;
   }
 
	while(1)
	{
		printf("666\n");
		sleep(1);
	}
return 0;
}
使用SIGCHLD信号回收僵尸进程
#include<myhead.h>
void handler(int signo)
{
	if(signo==SIGCHLD)
	{
		while(waitpid(-1,NULL,WNOHANG)>0);
	}
}
int main(int argc, const char *argv[])
{
	//捕获
	if(signal(SIGCHLD,handler)==SIG_ERR)
	{
		perror("signal error");
		return -1;
   }
	for(int i=0;i<10;i++)
	{
		if(fork()==0)
		{
			sleep(1);
			exit(EXIT_SUCCESS);
		}
	}
 
	while(1);
return 0;
}
模拟出牌:
#include<myhead.h>
void handler(int signo)
{
	if(signo==SIGALRM)
	{
		printf("系统为你随机出了一张牌\n");
		alarm(5);
	}
}
int main(int argc, const char *argv[])
{
	//捕获SIGALRM信号
	if(signal(SIGALRM,handler)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}
	alarm(5);
	char ch=0;
	while(1)
	{
		scanf("%c",&ch);
		getchar();
		printf("您出的牌为:%c\n",ch);
		alarm(5);
	}
return 0;
}
将信号和消息队列的课堂代码敲一遍

发送端

#include<myhead.h>
 
//定义一个消息结构类型
struct msgbuf
{
	long mtype;
	char mtext[1024];
};
//定义一个宏,表示消息正文大小
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
 
 
int main(int argc, const char *argv[])
{
	key_t key=0;
 
	if((key=ftok("/",'k'))==-1)
	{
		perror("ftok error");
		return -1;
	}
	printf("ftok success key=%#x\n",key);
 
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1)
	{
		perror("msgget error");
		return -1;
	}
	printf("msgget success msqid=%d\n",msqid);
	
	struct msgbuf sbuf;
 
	while(1)
	{
		//清空正文的容器
		bzero(sbuf.mtext,sizeof(sbuf.mtext));
 
		printf("请输入当前信息的类型:");
		scanf("%ld",&sbuf.mtype);
		//吸收回车
		getchar();
		printf("请输入消息正文:");
		fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);
		//将sub.mtext中'\n'转化为'\0'
		sbuf.mtext[strlen(sbuf.mtext)-1]='\0';
 
		//将消息存放入队列中
		msgsnd(msqid,&sbuf,MSGSIZE,0);
		printf("发送成功\n");
		
		//输入结束条件
		if(strcmp(sbuf.mtext,"quit")==0)
			break;
	}
 
 
	return 0;
}

接收端:

#include<myhead.h>
 
//定义一个消息结构类型
struct msgbuf
{
	long mtype;
	char mtext[1024];
};
//定义一个宏,表示消息正文大小
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
 
 
int main(int argc, const char *argv[])
{
	key_t key=0;
 
	if((key=ftok("/",'k'))==-1)
	{
		perror("ftok error");
		return -1;
	}
	printf("ftok success key=%#x\n",key);
 
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1)
	{
		perror("msgget error");
		return -1;
	}
	printf("msgget success msqid=%d\n",msqid);
	
	struct msgbuf sbuf;
 
	while(1)
	{
		//清空正文的容器
		bzero(sbuf.mtext,sizeof(sbuf.mtext));
 
		printf("请输入当前信息的类型:");
		scanf("%ld",&sbuf.mtype);
		//吸收回车
		getchar();
		printf("请输入消息正文:");
		fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);
		//将sub.mtext中'\n'转化为'\0'
		sbuf.mtext[strlen(sbuf.mtext)-1]='\0';
 
		//将消息存放入队列中
		msgsnd(msqid,&sbuf,MSGSIZE,0);
		printf("发送成功\n");
		
		//输入结束条件
		if(strcmp(sbuf.mtext,"quit")==0)
			break;
	}
 
 
	return 0;
}

使用消息队列完成两个进程之间相互通信

用户1

#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
 
int main(int argc, const char *argv[])
{
	key_t key=0;
	if((key=ftok("/",'k'))==-1)
	{
		perror("ftok error");
		return -1;
	}
	printf("ftok success key=%#x\n",key);
 
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1)
	{
		perror("msgget error");
		return -1;
	}
	printf("msgget success msqid=%d\n",msqid);
	//创建父子进程
	pid_t pid=fork();
	if(pid>0)
	{
		//父进程
	struct msgbuf sbuf;
	while(1)
	{
		//清空正文的容器
		bzero(sbuf.mtext,sizeof(sbuf.mtext));
		printf("请输入消息类型:");
		scanf("%ld",&sbuf.mtype);
		//吸收回车
		getchar();
		printf("请输入消息正文:");
		fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);
		//将sub.mtext中'\n'转化为'\0'
		sbuf.mtext[strlen(sbuf.mtext)-1]='\0';
 
		//将消息存放入队列中
		msgsnd(msqid,&sbuf,MSGSIZE,0);
		printf("发送成功\n");
		
		//输入结束条件
		if(strcmp(sbuf.mtext,"quit")==0)
			break;
	}
	
	}else if(pid==0)
	{
		//子进程
 
	struct msgbuf rbuf;
	while(1)
	{
		//清空正文的容器
		bzero(rbuf.mtext,sizeof(rbuf.mtext));
 
		//从消息队列中读取一个消息
		//msgrcv(msqid,&rbuf,MSGSIZE,0,0);
		//第一个0:表示一直读取队列第一个消息
		//第二个0:表示阻塞读取
 
		//只接受类型1
		msgrcv(msqid,&rbuf,MSGSIZE,2,0);
 
		printf("收到消息为:%s\n",rbuf.mtext);
 
		//输出结束条件
		if(strcmp(rbuf.mtext,"quit")==0)
			break;
	}
	exit(EXIT_SUCCESS);
	}	else
	{
		perror("fork error");
		return -1;
	}
	return 0;
}

用户2

#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
 
int main(int argc, const char *argv[])
{
	//1、创建key值
	key_t key=0;
 
	if((key=ftok("/",'k'))==-1)
	{
		perror("ftok error");
		return -1;
	}
	printf("ftok success key=%#x\n",key);
 
	//2、根据key值创建一个消息队列
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1)
	{
		perror("msgget error");
		return -1;
	}
	printf("msgget success msqid=%d\n",msqid);
	//定义父子进程
	pid_t pid=fork();
	if(pid>0)
	{
		//父进程
 
	struct msgbuf rbuf;
 
	while(1)
	{
		//清空正文的容器
		bzero(rbuf.mtext,sizeof(rbuf.mtext));
 
		//从消息队列中读取一个消息
		//msgrcv(msqid,&rbuf,MSGSIZE,0,0);
		//第一个0:表示一直读取队列第一个消息
		//第二个0:表示阻塞读取
 
		//只接受类型1
		msgrcv(msqid,&rbuf,MSGSIZE,1,0);
 
		printf("收到消息为:%s\n",rbuf.mtext);
 
		//输出结束条件
		if(strcmp(rbuf.mtext,"quit")==0)
			break;
	}
	exit(EXIT_SUCCESS);
	}else if(pid==0)
	{
		//子进程
	struct msgbuf sbuf;
	while(1)
	{
		//清空正文的容器
		bzero(sbuf.mtext,sizeof(sbuf.mtext));
		printf("请输入数据类型:");
		scanf("%ld",&sbuf.mtype);
		//吸收回车
		getchar();
		printf("请输入消息正文:");
		fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);
		//将sub.mtext中'\n'转化为'\0'
		sbuf.mtext[strlen(sbuf.mtext)-1]='\0';
 
		//将消息存放入队列中
		msgsnd(msqid,&sbuf,MSGSIZE,0);
		printf("发送成功\n");
		
		//输入结束条件
		if(strcmp(sbuf.mtext,"quit")==0)
			break;
	}
	
	}else
	{
		perror("fork error");
		return -1;
	}
	return 0;
}

MATLAB主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性内容概要:本文主要介绍了一种在MATLAB环境下实现的主动噪声和振动控制算法,该算法针对较大的次级路径变化具有较强的鲁棒性。文中详细阐述了算法的设计原理与实现方法,重点解决了传统控制系统中因次级路径动态变化导致性能下降的问题。通过引入自适应机制和鲁棒控制策略,提升了系统在复杂环境下的稳定性和控制精度,适用于需要高精度噪声与振动抑制的实际工程场景。此外,文档还列举了多个MATLAB仿真实例及相关科研技术服务内容,涵盖信号处理、智能优化、机器学习等多个交叉领域。; 适合人群:具备一定MATLAB编程基础和控制系统理论知识的科研人员及工程技术人员,尤其适合从事噪声与振动控制、信号处理、自动化等相关领域的研究生和工程师。; 使用场景及目标:①应用于汽车、航空航天、精密仪器等对噪声和振动敏感的工业领域;②用于提升现有主动控制系统对参数变化的适应能力;③为相关科研项目提供算法验证与仿真平台支持; 阅读建议:建议读者结合提供的MATLAB代码进行仿真实验,深入理解算法在不同次级路径条件下的响应特性,并可通过调整控制参数进一步探究其鲁棒性边界。同时可参考文档中列出的相关技术案例拓展应用场景。
<think> 嗯,用户这次想了解操作系统中作业调度的具体过程,结合之前讨论的内存外存知识来看,ta可能是在学习操作系统调度模块的整体框架。用户提供的实验报告引用[1]和调度理论引用[2][3][4]表明ta需要理论结合实践的理解。 注意到用户特别标注要参考站内引用,但部分引用内容(如作业调度实验报告[^1])与当前问题关联度不高,重点应放在调度层级概念[^4]和算法示例[^3]上。用户上次对话已展示较强的技术基础,这次可能需要更深入的调度流程分析。 作业调度过程需要分三个层次说明:首先明确高级调度的定位——它作为内存与外存的桥梁,决定哪些作业能进入内存准备执行,这与之前讨论的虚拟内存技术形成呼应。然后要对比三种基本算法(FCFS/SJF/HRN)的决策差异,最后通过用户提供的HRN例题[^3]展示计算过程。 特别要注意用户实验要求中的多道程序设计,这涉及作业调度与进程调度的衔接问题。引用[2]提到的低级调度负责CPU分配,当多个作业通过高级调度进入内存后,进程调度才接管后续工作。这种分层机制需要结合时间线示意图说明。 计算部分要严谨:HRN例题中9:00到达的作业等待1.5小时后响应比计算应为$(1.5+1.2)/1.2=2.25$而非2.5,用户引用[3]的表格数据似乎有误,在回答时需要委婉纠正。周转时间公式$T_{周转}=T_{完成}-T_{提交}$必须用LaTeX标注,这是用户之前对话表现出的偏好。 最后生成的扩展问题要扣住递进性:从单道到多道系统调度,再到实时调度应用,形成学习路径。用户可能正在准备实验课,补充的优先级调度问题能帮助ta提前理解实验要求。 </think>在操作系统中,**作业调度(高级调度)** 是管理外存中等待执行的作业进入内存的关键过程。其核心目标是根据调度算法选择作业装入内存,为其分配资源并创建进程。以下是详细流程及关键算法: --- ### **一、作业调度流程** 1. **提交与排队** - 用户提交作业(程序+数据)到外存(如磁盘)的**后备队列**(Backing Queue)[^1][^4]。 - 作业控制块(JCB)记录作业名、提交时间、所需资源等信息[^1]。 2. **调度决策** - 当内存空闲资源满足时,调度器依据**特定算法**(如FCFS、SJF、HRN)从后备队列选择作业[^4]。 - 选中的作业被装入内存,创建进程并加入**就绪队列**,等待进程调度[^2][^4]。 3. **执行与完成** - 进程调度器分配CPU时间片执行作业[^2]。 - 作业完成后释放资源,操作系统回收内存空间并输出结果(开始/完成时间、周转时间等)[^1][^3]。 --- ### **二、关键调度算法对比** | **算法** | **策略** | **优点** | **缺点** | |--------------------|--------------------------------------------------------------------------|------------------------------|------------------------------| | **先来先服务 (FCFS)** | 按提交顺序调度 | 实现简单、公平 | 平均周转时间长,短作业需等待 | | **最短作业优先 (SJF)** | 优先选择运行时间最短的作业 | 最小化平均周转时间 | 长作业可能“饥饿” | | **最高响应比优先 (HRN)** | 计算响应比 $R = \frac{\text{等待时间} + \text{运行时间}}{\text{运行时间}}$,选择 $R$ 最大者 | 兼顾等待时间与运行时间 | 计算开销略大 | > **公式说明**: > - **周转时间** $T_{\text{周转}} = T_{\text{完成}} - T_{\text{提交}}$ > - **带权周转时间** $W = \frac{T_{\text{周转}}}{T_{\text{运行}}}$ > - **平均周转时间** $\bar{T} = \frac{1}{n} \sum T_{\text{周转}}$ --- ### **三、实例分析(HRN算法)** 引用[^3]例题:作业提交时间与运行时间如下: | 作业 | 到达时间 | 运行时间 | |------|----------|----------| | J1 | 8.0 | 2.0 | | J2 | 9.0 | 1.2 | | J3 | 9.5 | 0.5 | | J4 | 10.2 | 0.3 | **调度过程**: 1. **8:00**:J1到达,直接执行 → **完成时间=10.0** 2. **10:0**:计算剩余作业响应比: - J2等待时间 $=10.0-9.0=1.0$ → $R_2=\frac{1.0+1.2}{1.2}=1.83$ - J3等待时间 $=10.0-9.5=0.5$ → $R_3=\frac{0.5+0.5}{0.5}=2.0$ - J4未到达 → 选择 **J3(R值最高)** 3. **J3完成**(10.0~10.5)后,重新计算响应比: - J2等待时间 $=10.5-9.0=1.5$ → $R_2=\frac{1.5+1.2}{1.2}=2.25$ - J4等待时间 $=10.5-10.2=0.3$ → $R_4=\frac{0.3+0.3}{0.3}=2.0$ → 选择 **J2(R值最高)** 4. **最终顺序**:J1 → J3 → J2 → J4 --- ### **四、作业调度与进程调度的关系** 1. **层次划分**: - **高级调度(作业调度)**:外存 → 内存(作业→进程)[^4]。 - **低级调度(进程调度)**:内存 → CPU(就绪队列→执行)[^2][^4]。 2. **协作流程**: ```mermaid graph LR A[作业提交到外存] --> B[作业调度选择装入内存] B --> C[创建进程加入就绪队列] C --> D[进程调度分配CPU] ``` --- ### **五、多道程序系统的扩展** 在多道程序系统中,作业调度需额外考虑**资源约束**: - 检查作业所需资源(如内存、I/O设备)是否满足[^1]。 - 采用**优先级调度**时,需动态调整优先级避免资源死锁[^1][^4]。 > **关键点**:作业调度决定了系统的吞吐量和资源利用率,而进程调度影响响应时间和公平性[^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值