目录
死锁
实验一:LINUX环境体验
第一关 LINUX环境目录
第二关:Linux文件操作命令
第三关Linux权限管理
Linux系统的进程控制
第1关:进程创建
第2关:进程加载
第3关:进程等待与退出
生产者消费者问题实践
第1关:生产者消费者问题实践
处理机调度
第1关:先来先服务调度算法
第2关:短作业优先调度算法
第3关:高相应比优先调度算法
动态分区算法
第2关:最佳适应算法
1、系统出现死锁时一定同时保持了四个必要条件,对资源采用按序分配算法后可破坏的条件是(A)。
A、循环等待条件2、资源的静态分配算法在解决死锁问题中是用于(B)。
A、避免死锁3、产生系统死锁的原因可能是由于(A)。
A、多个进程竞争资源出现了循环等待4、为了避免系统可能出现死锁,分配资源可以采用的算法是(D)。
A、抢占式分配5、某系统采用了银行家算法,则下列说法正确的是(C)。
A、系统处于安全状态时一定会发生死锁6、银行家算法中的数据结构包括可用资源向量Available、最大需求矩阵Max、分配矩阵Allocation、需求矩阵Need,下列选项中表述正确的是(B)。
A、Max[i,j]=Available[i,j]+Need[i,j]7、下列选项中,属于检测死锁的方法是(A)。
A、资源分配图简化法8、下列选项中,属于解除死锁的方法是(B)。
A、资源分配图简化法9、产生死锁的必要条件有(ABCD)。
A、循环等待10、用银行家算法避免死锁时,检测到(D)时才分配资源。
A、进程已占用的资源数与本次申请的资源数之和不超过对资源的最大需求量,且现存资源能满足尚需的最大资源量启动环境、打开终端
(1)在根目录下创建一个文件夹命名为linux
mkdir linux
(2)在根目录下创建一个文件命名为hello.txt
touch hello.txt
(3)将文件复制到linux文件夹下,并且改名为1.txt
cp hello.txt linux/1.txt
(4)删除根目录下的hello.txt
rm hello.txt
cd /home/headless
vi test.txt
输入:
Hello,Linux!
按ESC,再按 :wq
切记按顺序一个一个来,如果过不了就重新启动环境
cd /root
touch oldFile1 oldFile2 oldFile3 oldFile4
chmod u+x oldFile1
chmod g-r oldFile2
chmod o+x oldFile3
chmod u=r,g=w,o=x oldFile4
通过提示,在右侧编辑器中补充代码,完成在指定文件中添加内容,具体要求如下:
- 创建进程;
- 父进程向文件中添加
hello
和world!
;- 子进程向文件中添加
hello
和welcome!
;- 只需修改文件内容即可,平台将为你输出文件内容。
提示:fork()
函数的返回值为0
时则为子进程。
#include
#include
#include
#include
int main(){
FILE *fp = fopen("test.txt", "w+");
int pid; //pid表示fork函数的返回值
// 检查文件是否成功打开
if (fp == NULL) {
printf("File open error!\n");
return 1;
}
pid = fork(); // 创建子进程
if (pid < 0) {
// fork失败
printf("Fork failed!\n");
return 1;
} else if (pid == 0) {
// 子进程
fprintf(fp, "hello welcome!\n");
} else {
// 父进程
fprintf(fp, "hello world!\n");
}
fclose(fp); // 关闭文件
return 0;
}
在右侧编辑器补充代码,要求如下:
- 创建进程;
- 在父进程中输出
entering main process---
;- 在子进程中使用
execl()
函数调用src/step2/hello.c
文件,测试环境中已将path
置为src/step2
,因此带路径的文件名为./hello
#include
#include
#include
//请在此处添加导入相应库函数代码
int main(){
/********** Begin **********/
//父进程输出
int pid;
pid=fork();
if(pid==0)
{
execl("./hello",NULL);
}
else
{
printf("entering main process---\n");
}
//子进程执行hello.c文件
/********** End **********/
return 0;
}
根据提示,在右侧编辑器补充代码,创建两个子进程,第一个进程打印I am first process!
,第二个进程打印I am second process!
,父进程打印I am father process!
。
要求实现先打印第一个进程内容,再打印第二个进程内容,最后打印父进程内容。
提示:进程加载execl
函数调用输出用法execl("/bin/echo","echo", "输出语句", NULL);
#include
#include
#include
#include
//请在此处添加导入相应库函数代码
int main()
{
int p1, p2; //进程ID
/********** Begin **********/
p1=fork();
if(p1==0)
execl("/bin/echo","echo", "I am first process!", NULL);
else
wait(NULL);
p2=fork();
if(p2==0)
execl("/bin/echo","echo", "I am second process!", NULL);
else
wait(NULL);
printf("I am father process!");
//execl("/bin/echo","echo",NULL);
/********** End **********/
return 0;
}
void *Consumer()
{
int nextc = 0;
int i = 0;
for (; i < 10; ++i)
{
sem_wait(&full);
pthread_mutex_lock(&mutex);
nextc = buffer[out];
printf("Consume one message:%d\n", nextc);
fflush(stdout);
out = (out + 1) % SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}
第二关生产者消费者问题实践
void *Son()
{
//请添加儿子线程的函数代码
while(1)
{
int time = rand() % 10 + 1; //随机使程序睡眠0点几秒
usleep(time * 100000);
sem_wait(&orange);
pthread_mutex_lock(&mutex);
printf("儿子取了一个桔子\n") ;
fflush(stdout);
pthread_mutex_unlock(&mutex); //互斥锁解锁
sem_post(&empty);
}
}
#include
#include
#define N 5
typedef struct JCB
{
char name[10];
int arriveTime; //到达时间
int serveTime; //服务时间
int finishTime; //完成时间
int aroundTime; //周转时间
float waroundTime; //带权周转时间
}PCB;
void input(PCB pcb[N])
{
strcpy(pcb[0].name,"A");
pcb[0].arriveTime = 0;
pcb[0].serveTime = 3;
strcpy(pcb[1].name,"B");
pcb[1].arriveTime = 2;
pcb[1].serveTime = 6;
strcpy(pcb[2].name,"C");
pcb[2].arriveTime = 4;
pcb[2].serveTime = 4;
strcpy(pcb[3].name,"D");
pcb[3].arriveTime = 6;
pcb[3].serveTime = 5;
strcpy(pcb[4].name,"E");
pcb[4].arriveTime = 8;
pcb[4].serveTime = 2;
int i = 0;
for(; i < N; ++i)
{
pcb[i].finishTime = 0;
pcb[i].aroundTime = 0;
pcb[i].waroundTime = 0;
}
}
void output(PCB pcb[N])
{
int i = 0;
printf("进程\t");
printf("完成时间\t");
printf("周转时间\t");
printf("带权周转时间\t\n");
for(; i < N; ++i)
{
printf("%s\t",pcb[i].name);
printf("%d\t\t",pcb[i].finishTime);
printf("%d\t\t",pcb[i].aroundTime);
printf("%f\t\t\n",pcb[i].waroundTime);
}
}
//先来先服务调度算法
void FCFS(PCB pcb[N])
{
//请补充先来先服务算法的实现代码
int finished=0;
int curTime=0;
while(finished0||pcb[i].arriveTime>curTime)
{
continue;
}
if(pcb[i].arriveTime
#include
#include
#define N 5
typedef struct JCB
{
char name[10];
int arriveTime; //到达时间
int serveTime; //服务时间
int finishTime; //完成时间
int aroundTime; //周转时间
float waroundTime; //带权周转时间
}PCB;
void input(PCB pcb[N])
{
strcpy(pcb[0].name,"A");
pcb[0].arriveTime = 0;
pcb[0].serveTime = 3;
strcpy(pcb[1].name,"B");
pcb[1].arriveTime = 2;
pcb[1].serveTime = 6;
strcpy(pcb[2].name,"C");
pcb[2].arriveTime = 4;
pcb[2].serveTime = 4;
strcpy(pcb[3].name,"D");
pcb[3].arriveTime = 6;
pcb[3].serveTime = 5;
strcpy(pcb[4].name,"E");
pcb[4].arriveTime = 8;
pcb[4].serveTime = 2;
int i = 0;
for(; i < N; ++i)
{
pcb[i].finishTime = 0;
pcb[i].aroundTime = 0;
pcb[i].waroundTime = 0;
}
}
void output(PCB pcb[N])
{
int i = 0;
printf("进程\t");
printf("完成时间\t");
printf("周转时间\t");
printf("带权周转时间\t\n");
for(; i < N; ++i)
{
printf("%s\t",pcb[i].name);
printf("%d\t\t",pcb[i].finishTime);
printf("%d\t\t",pcb[i].aroundTime);
printf("%f\t\t\n",pcb[i].waroundTime);
}
}
//短作业优先调度算法
void SJF(PCB pcb[N])
{
for(int i=2;ipcb[j].serveTime)
{
PCB a=pcb[i];
pcb[i]=pcb[j];
pcb[j]=a;
}
}
double time=pcb[0].arriveTime;
for(int i=0;ipcb[j].arriveTime)
{
PCB a=pcb[i];
pcb[i]=pcb[j];
pcb[j]=a;
}
}
}
int main()
{
PCB pcb[N];
input(pcb);
SJF(pcb);
printf("短作业优先SJF:\n");
output(pcb);
printf("\n");
}
#include
#include
#define N 5
typedef struct JCB
{
char name[10];
int arriveTime; //到达时间
int serveTime; //服务时间
int finishTime; //完成时间
int aroundTime; //周转时间
float waroundTime; //带权周转时间
}PCB;
void input(PCB pcb[N])
{
strcpy(pcb[0].name,"A");
pcb[0].arriveTime = 0;
pcb[0].serveTime = 3;
strcpy(pcb[1].name,"B");
pcb[1].arriveTime = 2;
pcb[1].serveTime = 6;
strcpy(pcb[2].name,"C");
pcb[2].arriveTime = 4;
pcb[2].serveTime = 4;
strcpy(pcb[3].name,"D");
pcb[3].arriveTime = 6;
pcb[3].serveTime = 5;
strcpy(pcb[4].name,"E");
pcb[4].arriveTime = 8;
pcb[4].serveTime = 2;
int i = 0;
for(; i < N; ++i)
{
pcb[i].finishTime = 0;
pcb[i].aroundTime = 0;
pcb[i].waroundTime = 0;
}
}
void output(PCB pcb[N])
{
int i = 0;
printf("进程\t");
printf("完成时间\t");
printf("周转时间\t");
printf("带权周转时间\t\n");
for(; i < N; ++i)
{
printf("%s\t",pcb[i].name);
printf("%d\t\t",pcb[i].finishTime);
printf("%d\t\t",pcb[i].aroundTime);
printf("%f\t\t\n",pcb[i].waroundTime);
}
}
//高响应比优先调度算法
void HRRN(PCB pcb[N])
{
for(int i=3;ipcb[j].serveTime)
{
PCB a=pcb[i];
pcb[i]=pcb[j];
pcb[j]=a;
}
}
double time=pcb[0].arriveTime;
for(int i=0;ipcb[j].arriveTime)
{
PCB a=pcb[i];
pcb[i]=pcb[j];
pcb[j]=a;
}
}
}
int main()
{
PCB pcb[N];
input(pcb);
HRRN(pcb);
printf("高响应比优先HRRN:\n");
output(pcb);
}
#include
#include
const int Max_length=55;//最大内存
struct areaNode//管理分区的结构体
{
int ID;//分区号
int size;//分区大小
int address;//分区地址
int flag;//使用状态,0为未占用,1为已占用
};
typedef struct DuNode//双向链表结点
{
struct areaNode data;//数据域
struct DuNode *prior;//指针域
struct DuNode *next;
}*DuLinkList;
DuLinkList m_head = new DuNode, m_last = new DuNode;//双向链表首尾指针
void init()//分区链表初始化
{
m_head->prior = NULL;
m_head->next = m_last;
m_last->prior = m_head;
m_last->next = NULL;
m_head->data.size = 0;
m_last->data.address = 0;
m_last->data.size = Max_length;
m_last->data.ID = 0;
m_last->data.flag = 0;
}
void show()
{
DuNode *p = m_head->next;//指向空闲区队列的首地址
printf("+++++++++++++++++++++++++++++++++++++++\n");
while (p)
{
printf("分区号:");
if (p->data.ID == 0)
printf("FREE\n");
else
printf("%d\n",p->data.ID);
printf("分区起始地址:%d\n",p->data.address);
printf("分区大小:%d\n",p->data.size);
printf("分区状态:");
if (p->data.flag)
printf("已被占用\n");
else
printf("空闲\n");
printf("——————————————————\n");
p = p->next;
}
}
bool first_fit(int id,int m_size)//首次适应算法,id为作业号,m_size为作业大小
{
//请补充使用首次适应算法给作业分配内存的函数代码
DuLinkList p = m_head;
while(p != m_last) {
DuLinkList n = p->next;
if(!n->data.flag && n->data.size >= m_size) {
DuLinkList t = new DuNode();
t->data.ID = id;
t->data.size = m_size;
t->data.address = n->data.address;
t->data.flag = 1;
n->data.address += m_size;
n->data.size -= m_size;
t->prior = p;
t->next = n;
p->next = t;
n->prior = t;
}
p = n;
}
}
void recycle(int id)//回收内存,id为释放内存的作业号
{
DuLinkList p = m_head;
while(p != m_last) {
DuLinkList n = p->next;
if(n->data.ID == id) {
p->next = n->next;
n->next->prior = p;
n->next->data.address -= n->data.size;
m_last->data.size += n->data.size;
delete n;
n = n->next;
}
if(n != m_last)
n->next->data.address = n->data.address + n->data.size;
p = n;
}
}
int main()
{
init();
printf("首次适应算法:\n");
first_fit(1,15);
first_fit(2,30);
recycle(1);
first_fit(3,8);
first_fit(4,6);
recycle(2);
show();
DuNode *p = m_head;
while(p != NULL)
{
DuNode *temp = p;
p = p->next;
delete(temp);
temp = NULL;
}
return 0;
}
#include
#include
const int Max_length=55;//最大内存
struct areaNode//管理分区的结构体
{
int ID;//分区号
int size;//分区大小
int address;//分区地址
int flag;//使用状态,0为未占用,1为已占用
};
typedef struct DuNode//双向链表结点
{
struct areaNode data;//数据域
struct DuNode *prior;//指针域
struct DuNode *next;
}*DuLinkList;
DuLinkList m_head = new DuNode, m_last = new DuNode;//双向链表首尾指针
void init()//分区链表初始化
{
m_head->prior = NULL;
m_head->next = m_last;
m_last->prior = m_head;
m_last->next = NULL;
m_head->data.size = 0;
m_last->data.address = 0;
m_last->data.size = Max_length;
m_last->data.ID = 0;
m_last->data.flag = 0;
}
void show()
{
DuNode *p = m_head->next;//指向空闲区队列的首地址
printf("+++++++++++++++++++++++++++++++++++++++\n");
while (p)
{
printf("分区号:");
if (p->data.ID == 0)
printf("FREE\n");
else
printf("%d\n",p->data.ID);
printf("分区起始地址:%d\n",p->data.address);
printf("分区大小:%d\n",p->data.size);
printf("分区状态:");
if (p->data.flag)
printf("已被占用\n");
else
printf("空闲\n");
printf("——————————————————\n");
p = p->next;
}
}
bool best_fit(int id, int m_size)//最佳适应算法,其中需要查找最佳的存放位置
{
//请补充使用最佳适应算法给作业分配内存的函数代码
DuLinkList p = m_head;
DuLinkList t = nullptr;
while(p != m_last) {
DuLinkList n = p->next;
if(!n->data.flag && n->data.size >= m_size) {
if(t == nullptr || t->data.size > n->data.size){
t = n;
}
}
p = n;
}
if(t == nullptr)
return false;
if(t->data.size == m_size) {
t->data.flag = 1;
t->data.ID = id;
}
else {
DuLinkList t2 = new DuNode();
t2->next = t;
t2->prior = t->prior;
t->prior->next = t2;
t->prior = t2;
t2->data.ID = id;
t2->data.flag = 1;
t2->data.address = t->data.address;
t->data.address += m_size;
t2->data.size = m_size;
t->data.size -= m_size;
}
return true;
}
void recycle(int id)//回收内存,id为释放内存的作业号
{
//请补充回收作业内存的函数代码
DuLinkList p = m_head;
DuLinkList n = nullptr;
while(p != m_last) {
n = p->next;
if(n->data.ID == id) {
break;
}
p = n;
}
if(n == nullptr || n == m_last)
return;
n->data.flag = 0;
n->data.ID = 0;
DuLinkList np = n->prior;
DuLinkList nn = n->next;
if(np != m_head && np->data.flag == 0) {
np->prior->next = n;
n->prior = np->prior->next;
n->data.address = np->data.address;
n->data.size += np->data.size;
delete np;
}
if((nn != nullptr || nn != m_last) && nn->data.flag == 0) {
nn->next->prior = n;
n->next = nn->next->prior;
n->data.size += nn->data.size;
delete nn;
}
}
int main()
{
init();
//最佳适应算法
printf("最佳适应算法:\n");
init();
best_fit(1,15);
best_fit(2,30);
recycle(1);
best_fit(3,8);
best_fit(4,6);
recycle(2);
show();
DuNode *p = m_head;
while(p != NULL)
{
DuNode *temp = p;
p = p->next;
delete(temp);
temp = NULL;
}
return 0;
}