操作系统原理分析要点
https://www.cnblogs.com/huyufeng/p/5400639.html
进程的调度时机与进程切换机制
-------------
调度时机
中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();
内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度
---------
进程的切换
进程切换 任务切换 上下文切换
1 switch_to 宏 schedule() 进程描述符地址
2 进程切换-内核栈切换实施
A用户态(中断、异常、系统调用,用户栈保存在内核栈,ESP到栈底)--A内核态
A内核态(内核栈切换)--B内核态
B内核态(取出1用户栈信息、装载寄存器)--B用户态
====================================
i_addr[0]1483
i_addr[1]24
i_addr[2]225
i_addr[3]542
i_addr[4]2212
i_addr[5]98
i_addr[6]3321
i_addr[7]23
i_addr[8]123
i_addr[9]67---[n=10]
i_addr[10]326*
i_addr[11]756*
i_addr[12]226*
第326块
……
[11]109
[12]954
[13]952
……
第756块
[0]53**
[1]922**
……
第53块
……
[211]863
[212]335
……
第922块
……
[211]2312
[212]3276
……
假设某文件的i-node结构及各级索引表如上所示,如果物理块长度为X=1KB,块号Y=4B
1.该文件的读写指针指示地址为6820,给出该 地址所在的物理块号和块内地址
2.该文件的读写指针指示地址为22675,给出 该地址所在的物理块号和块内地址
3.该文件的读写指针指示地址为751155,给 出该地址所在的物理块号和块内地址
解:
a=log2(XKB/8bit)=log2(2^10)=10
0~9 有n=10
b=X KB/Y B=X*2^10/Y=2^8
(1)x1=6820
index=x1>>a=x1/(2^a)取整=6<n
w=x1&11……(a个1)=x1%(2^a)取余数=676
物理块号3321(PS:i_addr[6]3321)
块内地址676(PS:w)
(2)x1=22675
index=x1>>a=x1/(2^a)取整=22
w=x1&11……(a个1)=x1%(2^a)取余数=147<b
index=index-n=12
物理块号954(PS:i_addr[10]326*[12]954 )
块内地址147(PS:w)
(3)x1=751155
index=x1>>a=x1/(2^a)取整=733
w=x1&11……(a个1)=x1%(2^a)取余数=563
index=index-n=723
index=index-b=467
index÷b=index2(商)……w2(余数)
index2=1
w2=211
物理块号2321(PS:i_addr[11]756*[1]922**[211]2312)
块内地址563(PS:w)
=====================================
7 6 5 4 3 2 1 0
0_1_1_0_1_1_1_1
15 14 13 12 11 10 9 8
1__1___0__0__1__1_1_1
23 22 21 20 19 18 17 16
0__1__0__1__0__1___1__0
31 30 29 28 27 26 25 24
0__0__0__0__1__0___1__0
某静态页式存储管理中,已知内存共有X=32块 ,块长度为Y=4K=2^12=4096,(假设单位一样),当前位
示图如上,进程P的虚拟地址空间大小为ADD=35655。
1.当前有几个空闲块[PS:数一下位示图上有0] 14个
2.进程P共有几页[PS:ADD除以Y,商整数只入不舍 相当于
(ADD+Y-1)/Y取整数部分]
(35655+4K-1)/4K=9页
3.根据位示图,写出进程P的页表
[0]4
[1]7
[2]12
[3]13
[4]16
[5]19
[6]21
[7]23
[8]24
4.给定进程P的虚拟地址:9198和 ox9D8F,根据(3)分别计算对应的物理地址
十进制的9198:
页号p=9198/4K=2;页内地址w=9198%4K=1006
块号b=12(PS:[p]12)
物理地址=b*4K+1006=50158
十六进制ox9D8F:
页号p=1001 1101 1000 1111>>12=1001
p=9不小于9,越界
https://blog.csdn.net/u011209099/article/details/9248525 多了cr3和页目录介绍
=======================================================
实验一 并发程序设计
1.目的
在单处理器环境下,实现多任务的核心是并发程序设计,进程的并发执行提高了CPU的利用率,使得CPU与设备并行、设备与设备并行成为可能。但并发执行的一些进程之间需要互斥和同步的控制。
在应用系统开发中,几乎都需要使用数据库系统,在多用户操作时,对数据库中一些表的操作也需要互斥或同步。
2.要求
题目:在BACC环境下,对程序并发执行的实验:(1)没有控制时正确的程序执行的结果不正确;(2)BACC中PV操作的并发控制的实现。
要求:
(1)学习Windows命令接口中部分基本命令的使用
(2)BACC的使用:
(3)BACC中PV操作的并发控制的实现。
(4)将课堂和习题中的同步、互斥的并发程序设计的习题的设计与实现。
二、实验内容
1.pop ()和push (100)各执行一次的结果(堆栈)
有并发控制的(两种答案)
semaphore s=1;
int stack[20];
int top;
void pop(){
int free;
p(s);
free=stack[top];
top--;
cout<<"out:"<<free<<endl;
v(s);
}
void push(int free){
p(s);
top++;
stack[top]=free;
cout<<"in:"<<free<<endl;
v(s);
}
main()
{
int i;
for(i=0;i<20;i++)stack[i]=-1;
stack[0]=0;
stack[1]=156;
stack[2]=254;
stack[3]=129;
stack[4]=23;
top=4;
cobegin{
pop();push(100);}
cout<<"top_point="<<top<<endl;
for(i=0;i<=top;i++)
cout<<"stack["<<i<<"]="<<stack[i]<<endl;
}
2.同步关系
假定有三个进程R、W1、W2共享一个缓冲区B,而B每次只能存放一个整数。当缓冲区中无数时,进程R可以从输入设备上读入一个整数并存入B中;若存到B中的数是奇数,则允许进程W1将其取出打印;若是偶数,则允许进程W2将其取出打印。另外规定:进程R必须等B中的数被取出打印后才能再存放下一个数,进程W1或W2对每次存入的数只能打印一次并且都不能从空的缓冲区中取数。请用PV操作实现R、W1和W2三个进程的并发执行。
semaphore S = 1, SO = 0, SE = 0;
int B;
void R()
{
int x;
cin >> x;
p(S);
B = x;
if (B % 2 == 1)
v(SO);
else v(SE);
}
void W1()
{
int y;
p(SO);
y = B;
v(S);
cout << "print odd:" << y << endl;
}
void W2()
{
int z;
p(SE);
z = B;
v(S);
cout << "print even:" << z << endl;
}
main()
{
cobegin{ R(); R(); W1(); W2(); }
}
实验二 进程通信
一、目的与要求
1.目的
进程通信是多任务协作的基础,具有广泛的应用。熟悉Linux的基于消息队列的进程通信的系统调用,并实现一个简单的C/S结构的实例。
2.要求
题目:Linux进程通信及C/S结构应用。
(1)熟悉教材中有关进程通信方式。
(2)熟悉Linux的使用(常用shell命令、VI、CC等)。
(3)熟悉Linux的消息结构定义, msgget()、msgrcv(msgqid,…)、msgsnd(msgqid,…)的系统使用,C/S结构的工作过程 。
二、实验内容
1.一个简单C/S结构 实现①a*X+b=0求x②反转字符串
msg_mycs.h:
#define MSGKEY 1183
struct msgform {
long mtype;
int source_pid;
double a,b;
char opcode;
double result;
char fanzhuan[128];
char return_msg[128];
}msg;
int msgsize=sizeof(struct msgform)-sizeof(long);
int msgqid;
B1.C:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "msg_mycs.h"
main()
{
struct msgform msg;
int pid;
int i;
msgqid = msgget(MSGKEY,0777);
pid = getpid();
msg.opcode != '1';
for(;msg.opcode!='q';){
printf("opcode=(1 for a*?+b=0; 2 forfanzhuan;q for EXIT)");
msg.opcode=getchar();
while(msg.opcode=='\n')msg.opcode=getchar();
if (msg.opcode == '1' || msg.opcode == '2')
{
if (msg.opcode == '1')
{
printf("a=");
scanf("%lf", &msg.a);
printf("b=");
scanf("%lf",&msg.b);
}
else{
printf("the string=");
scanf("%s", msg.fanzhuan);
}
msg.source_pid=pid;
msg.mtype=1;
msg.return_msg[0]=0;
msgsnd(msgqid,&msg,msgsize,0);
msgrcv(msgqid,&msg,msgsize,pid,0);
printf("client: receive from pid=%d\n",msg.source_pid);
if(msg.opcode=='1')
printf("%.2f* %.2f + %.2f = 0\n",msg.a,msg.result,msg.b);
else
printf("%s\n",msg.return_msg);
}
}
}
A1.C
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "msg_mycs.h"
main()
{
struct msgform msg;
int pid;
int i;
msgqid = msgget(MSGKEY,0777);
pid = getpid();
msg.opcode != '1';
for(;msg.opcode!='q';){
printf("opcode=(1 for a*?+b=0; 2 forfanzhuan;q for EXIT)");
msg.opcode=getchar();
while(msg.opcode=='\n')msg.opcode=getchar();
if (msg.opcode == '1' || msg.opcode == '2')
{
if (msg.opcode == '1')
{
printf("a=");
scanf("%lf", &msg.a);
printf("b=");
scanf("%lf",&msg.b);
}
else{
printf("the string=");
scanf("%s", msg.fanzhuan);
}
msg.source_pid=pid;
msg.mtype=1;
msg.return_msg[0]=0;
msgsnd(msgqid,&msg,msgsize,0);
msgrcv(msgqid,&msg,msgsize,pid,0);
printf("client: receive from pid=%d\n",msg.source_pid);
if(msg.opcode=='1')
printf("%.2f* %.2f + %.2f = 0\n",msg.a,msg.result,msg.b);
else
printf("%s\n",msg.return_msg);
}
}
}
2.一个简单C/S结构的基金账户管理
msg_mycs.h:
#define MSGKEY 1183
struct msgform {
long mtype;
int source_pid;
char nameid[10],password[10];
char opcode;
double result;
char return_msg[100];
}msg;
int msgsize=sizeof(struct msgform)-sizeof(long);
int msgqid;
b2.c
#include <stdlib.h> /*如果没有这个会提示貌似是 identifier or ‘(’ before 甚么甚么的错误*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/ioctl.h>/*如果没有这个会提示 define NULL 的错误*/
#include "msg_mycs.h"
struct usr
{
char name[10];
char pass[10];
double money;
struct usr *next;
}*head;
int registerr(struct msgform m);/*这个自己定义的函数名,本来是register,应该是头文件里面有个这个名字的,所以我就弄了另一个就ok了*/
struct usr* findbyName(struct msgform m);
main()
{
int i,j;
extern cleanup();
for(i=0;i<20;i++)
signal(i,cleanup);
msgqid = msgget(MSGKEY,0777|IPC_CREAT);
head= NULL;
struct usr *pointlist;
pointlist = NULL;
for(;msg.opcode!='q';)
{
printf("server pid= %d is ready (msgqid=%d)... \n",getpid(),msgqid);
msgrcv(msgqid,&msg,msgsize,1,0);
printf("server: receive from pid=%d\n",msg.source_pid);
switch(msg.opcode){
case '1':
j=registerr(msg);
if (j == 0)strcpy(msg.return_msg, "the account already exists ");
else strcpy(msg.return_msg, "register successfull");
break;
case '2':
pointlist=findbyName(msg);
if (pointlist == NULL)strcpy(msg.return_msg, "the account you required doesnot exist or password error");
else strcpy(msg.return_msg, "sign in successfull");
break;
case '3':if (pointlist != NULL )
{
pointlist->money+=msg.result;
strcpy(msg.return_msg, "deposit successfull");
} else strcpy(msg.return_msg, "error,please ask for help");
break;
case '4':
if (pointlist != NULL)
{
if (msg.result > 0 && pointlist->money > msg.result)
{
pointlist->money -= msg.result;
msg.result=pointlist->money;
strcpy(msg.return_msg, "withdraw successfull");
}
else strcpy(msg.return_msg, " insufficient balance ");
}
else strcpy(msg.return_msg, "withdraw error ");
break;
case '5':
if (pointlist!= NULL )
{
msg.result=pointlist->money ;
strcpy(msg.return_msg, "account balance");
}
else strcpy(msg.return_msg, "operation error ");
break;
}
msg.mtype=msg.source_pid;
msg.source_pid=getpid();
msgsnd(msgqid,&msg,msgsize,0);
}
pointlist = NULL;
printf("server eixt by client pid=%d\n",msg.mtype);
}
struct usr* findbyName(struct msgform m)
{
struct usr * tmp_node;
tmp_node = head;
while (tmp_node!= NULL)
{
if ((strcmp(tmp_node->name, m.nameid) == 0) &&( strcmp(tmp_node->pass, m.password) == 0)){return tmp_node;
}tmp_node = tmp_node->next;
}
return NULL;
}
int registerr (struct msgform m)
{
struct usr* tmp_node;
tmp_node = head;
while (tmp_node != NULL)
{
if (strcmp(tmp_node->name, m.nameid) == 0)return 0;
tmp_node = tmp_node->next;
}
tmp_node = malloc(sizeof(struct usr));
strcpy(tmp_node->name, m.nameid);
strcpy(tmp_node->pass, m.password);
tmp_node->money = m.result;
tmp_node->next = head;
head = tmp_node;
return 1;
}
cleanup()
{
msgctl(msgqid,IPC_RMID,0);
exit(0);
}
A2.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "msg_mycs.h"
main()
{
struct msgform msg;
int pid;
int i;
msgqid = msgget(MSGKEY,0777);
pid=getpid();
msg.opcode='1';
for(;msg.opcode!='q';){
printf("1:zhuce\n 2:dengru\n 3:cunk \n 4: quk \n 5:chaxun \n q:tuichu \n ");
msg.opcode=getchar();
while(msg.opcode=='\n')msg.opcode=getchar();
if(msg.opcode=='1'||msg.opcode=='2'){
printf("user:");
scanf("%s",&msg.nameid);
printf("password:");
scanf("%s",&msg.password);} else
if(msg.opcode=='3') { printf("cun monney:");
scanf("%lf",&msg.result);
} else if(msg.opcode=='4'){printf("qu monney:");
scanf("%lf",&msg.result);}
if(msg.opcode=='1'||msg.opcode=='2'||msg.opcode=='3'||msg.opcode=='4'||msg.opcode=='5')
{
msg.source_pid=pid;
msg.mtype=1;
msg.return_msg[0]=0;
msgsnd(msgqid,&msg,msgsize,0);
msgrcv(msgqid,&msg,msgsize,pid,0);
printf("client: receive from pid=%d\n",msg.source_pid);
switch (msg.opcode)
{
case '1':
case '2':
printf("%s\n", msg.return_msg);
break;
case '3':
case '4':
case '5':
printf("%s\n $=%lf\n", msg.return_msg, msg.result);
break;
}
}
}
}