模拟操作系统内核对进程的控制和管理:包括进程的创建和撤销、进程状态的切换和简单的内存空间管理。
1、 定义管理每个进程的数据结构PCB:包含进程名称、队列指针、分配的物理内存区域(基址和长度)。每创建一个进程时,需要为其创建PCB并分配空闲内存空间,对PCB进行初始化,并加入就绪队列。(斜体为可选)
可参考如下数据结构(动态形式):
|
struct PCB{ char name[8]; struct PCB *next; ... }; struct PCB *ready,*blocked,*running; |
创建进程时申请空白PCB:
|
struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB)); |
并把新建进程的PCB添加到就绪队列末尾:
|
add(ready,p); |
其中,ready为就绪队列头节点,并在开始处分配了空间;add函数是链表中添加节点函数,代码参考如下:
void add(struct PCB *head, struct PCB *process){
struct PCB *tmp=head;
while(tmp->next!=NULL)
tmp=tmp->next;
tmp->next=process;
process->next=NULL;
}
2、 模拟触发进程状态转换的事件:采用键盘控制方法来模拟触发进程状态切换的事件(例如输入1代表创建新进程、2执行进程时间片到、3阻塞执行进程、4唤醒第一个阻塞进程、5终止执行进程),实现对应的控制程序。
3、 根据当前发生的事件对进程的状态进行切换,并显示出当前系统中的执行队列、就绪队列和阻塞队列。
4、 *(选做)完成可变分区的分配与回收,创建进程的同时申请一块连续的内存空间,在PCB中设置好基址和长度,结束进程时回收分配的内存空间。分配可采用首次适应、最佳适应或最差适应算法,碎片大小为2Kb,最后回收所有进程的空间,对空间分区的合并。可以查看进程所占的空间和系统空闲空间。
可以用一个链表(如图1-1所示)来维护已分配的和空闲的内存段,其中一个段或者包含一个进程,或者是两个进程之间的空闲段。 在图1-1中,链表的每一项包含四个值域。第一个值域表示内存段是空闲或占用(例如,空闲段用H表示,进程占用的段用P表示);第二个值域表示内存段的起始位置,第三个值域表示内存段的长度;第四个值域为指向链表下一项的指针。该链表按照内存段的起始地址进行从小到大排序。这样排序的好处是方便内存空间的回收。一个要终止的进程一般会有两个邻居(除了在内存顶端和内存底端的进程)。邻居可能是进程也可能是空闲段。根据两个邻居的不同类型,可以分为四种回收情况(如图1-2所示)。在图1-2(a)中,对链表的更新只需要将P置为H;在图1-2(b)和(c)中,需要将P置为H,并将该项与另外一个相邻的空闲段的项合并为一项;在图1-2(d)中,需要将该项和两个邻居合并为一项。考虑到合并空闲段需要查看邻居,因此用双向链表会比单向链表更加方便。

图 1-1. (a) 内存空间的示例,有5个进程和3个空闲段,阴影部分表示空闲段。
(b) 管理内存空间的链表

图 1-2. 对终止的进程X的四种内存回收情况(阴影代表空闲区)
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
struct PCB{
char name[8];
struct PCB *next;
};
struct PCB *ready,*blocked,*running;
struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB));
//插入队列
void add(struct PCB *head,struct PCB *process){
struct PCB *tmp=head;
while(tmp->next!=NULL)
tmp=tmp->next;
tmp->next=process;
process->next=NULL;
}
//出队列
struct PCB *movefirst(struct PCB *head){
struct PCB *tmp=head->next;
if(tmp!=NULL)
{
head->next=tmp->next;
tmp->next=NULL;
}
return tmp;
};
//创建进程
void creat()
{
struct PCB *tmp;
char name[10];
cout<<"输入进程名字:";
cin>>name;
tmp=(struct PCB*)malloc(sizeof(struct PCB));
strcpy(tmp->name,name); //字符串复制函数
tmp->next=NULL;
add(ready,tmp);
if(running==NULL) //如果当前没有正在执行的进程就将新创建的进程运行
running=movefirst(ready);
}
//时间片到
void timeout(){
if(ready->next==NULL) // 容错处理
cout<<"\t\t就绪队列为空!"<<endl;
if(running!=NULL)
{
add(ready,running);
running=movefirst(ready);
}
else
running=movefirst(ready);
}
//阻塞进程
void block(){
if(running!=NULL)
{
add(blocked,running);
running=movefirst(ready);
}
else
cout<<"\t\t没有运行的进程,无法阻塞!"<<endl;
}
//唤醒进程
void wakeup(){
if (blocked->next == NULL){
printf("阻塞态已为空!!!\n");
}
else{
struct PCB *T = (struct PCB*)malloc(sizeof(struct PCB));
T = movefirst(blocked);
add(ready,T);
if (running == NULL){
running =movefirst(ready);
}
}
}
//终止进程
void stop(){
if(running!=NULL)
{
free(running);
running=movefirst(ready);
}
else
cout<<"\t\t没有运行的进程"<<endl;
}
//展示
void show()
{
struct PCB *tmp;
cout<<endl;
cout<<"执行队列:";
if(running!=NULL)
cout<<" "<<running->name;
cout<<endl;
cout<<"就绪队列:";
tmp=ready->next;
while(tmp!=NULL){
cout<<" "<<tmp->name;
tmp=tmp->next;
}
cout<<endl;
cout<<"阻塞队列:";
tmp=blocked->next;
while(tmp!=NULL){
cout<<" "<<tmp->name;
tmp=tmp->next;
}
cout<<endl;
cout<<endl;
}
//菜单
void menu()
{
cout<<"\t\t--------------------"<<endl;
cout<<"\t\t1.创建进程"<<endl;
cout<<"\t\t2.时间片到"<<endl;
cout<<"\t\t3.阻塞进程"<<endl;
cout<<"\t\t4.唤醒进程"<<endl;;
cout<<"\t\t5.终止进程"<<endl;
cout<<"\t\t6.退出程序"<<endl;
cout<<"\t\t--------------------"<<endl;
}
main()
{
ready=(struct PCB*)malloc(sizeof(struct PCB));
ready->next=NULL;
blocked=(struct PCB*)malloc(sizeof(struct PCB));
blocked->next=NULL;
int c;
while(1)
{
menu();
cout<<"输入功能:";
cin>>c;
switch(c)
{
case 1:
creat();
break;
case 2:
timeout();
break;
case 3:
block();
break;
case 4:
wakeup();
break;
case 5:
stop();
break;
case 6:
exit(0);
default:
cout<<"没有这个选项,请重新输入"<<endl;
}
show();
}
}
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新rubygems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------