操作系统第一次上机实验 进程控制(终极版)

实验一进程控制

一、      实验目的

1.       理解进程控制块的结构。 

2.       理解进程各种状态之间的转换过程。

3.       掌握进程创建与撤消的方法。

4.       掌握进程挂起与唤醒的方法。 

二、      实验设备

1.      安装windows或者linux操作系统的PC机

2.      C程序编译环境

三、      实验内容

用c语言编程模拟实现操作系统的进程控制过程。进程控制主要包括进程的创建与撤消、进程的挂起与唤醒等。

四、      实验要求

1.      上机编写并调试进程控制的模拟程序。

2.      要把相应的程序代码及程序运行结果写入实验报告中。

 

 

//操作系统—进制控制模拟
#include<stdio.h>
#include<stdlib.h>
#include <windows.h>
#include<tlhelp32.h>
#define N 10
struct pb
{
  int ko;
  int no;
  int cha;
};

typedef struct pb PCB;
PCB a[N];
int showallproc()
{
    PROCESSENTRY32 pe32;//用来存储进程信息的结构体
    pe32.dwSize=sizeof(pe32);
    HANDLE hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获取进程快照
    if(hProcessSnap==INVALID_HANDLE_VALUE)
    {
        printf("调用失败\n");
        return 1;
    }
    BOOL bProc=Process32First(hProcessSnap,&pe32);
    while(bProc)
    {
        printf("%5d %s\n",pe32.th32ProcessID,pe32.szExeFile);//输出进程ID和进程名
        bProc=Process32Next(hProcessSnap,&pe32);
    }
    CloseHandle(hProcessSnap);
    return 0;
}
static int count=1;
void create()   //创建
{
  static int pi=1;
  int k,l=0,m;
  printf("please input n0:");
  scanf("%d",&m);
  for(k= 1;k<= N;k++ )
    if(a[k].no ==m)
   l=1;
 if(l == 1)
 {
   printf("Error!\n");
   create();
 }
    else
 {
  for(k= 1;k<= N;k++ )
  {
   if(a[k].no==0)
   {
    pi=k;break;}
  }
   a[pi].no=m;
   printf("\nplease input ko0:");
   scanf("%d",&a[pi].ko);
   if(count>1)            //首次进程状态为执行,之后为活动就绪
     a[pi++].cha=3;
   else
     a[pi++].cha=5;
   count++;
 }
}

int stopproc()
{
    DWORD ProcessID;
    printf("请输入想要终止的进程ID\n");
    scanf(" %d",&ProcessID);
    HANDLE hProcess=OpenProcess(PROCESS_TERMINATE,FALSE,ProcessID);//打开对应进程句柄
    if (hProcess==NULL)
    {
        printf("失败\n");
        return -1;
    }
    if (!TerminateProcess(hProcess,0))//关闭进程
    {
        printf("关闭失败\n");
    }
    else
    {
        printf("关闭成功\n");
    }
    CloseHandle(hProcess);
   
    return 0;
}

void dispatch()   //调度
{
 int i,m,l=0,j=0,k,min=10000;

 for(m= 1;m<= N;m++ )
  if(a[m].cha==5)
   l=m;
  if(l!=0)
  {
   printf("Error!");
   return;
  }
  else
 for(k= 1;k<= N;k++ )
 {
  if(a[k].cha==3)
  if(min>a[k].ko)
  {
   min=a[k].ko;
      i=k;
   j=1;
  }
 }
     if(j)        
      a[i].cha=5;
        else if(j==0)
   printf("Error!\n");
 
}

void block()   //阻塞
{
  int k,m,l=0;
  printf("please input no0:");
  scanf("%d",&m);
  for(k= 1;k<= N;k++ )
    if(a[k].no==m)
   l=k;
 if(l!=0)
 {
   if(a[l].cha==3 || 5)
     a[l].cha=4;
  else if(a[l].cha==1)
    a[l].cha=2;
    else
    printf("Error!\n");
 }
 else
  printf("Error!");
}

void wakeup()   //唤醒
{
  int k,m,l=0;
  printf("please input no0:");
  scanf("%d",&m);
  for(k= 1;k<= N;k++ )
   if(a[k].no==m)
     l=k;
   if(l!=0)
   {
  if(a[l].cha==2)
    a[l].cha=1;
    else if(a[l].cha==4)
      a[l].cha=3;
      else
   printf("Error!\n");
   }
   else
    printf("Error!");
}


void suspend()   //挂起
{
  int k,m,l=0;
  printf("please input no0:");
  scanf("%d",&m);
  for(k= 1;k<= N;k++ )
    if(a[k].no==m)
   l=k;
 if(l!=0)
 {
   if(a[l].cha==3 || 5)
     a[l].cha=1;
  else if(a[l].cha==4)
    a[l].cha=2;
    else
    printf("Error!\n");
 }
 else
  printf("Error!");
}

void active()   //激活
{
  int k,m,l=0;
  printf("please input no0:");
  scanf("%d",&m);
  for(k= 1;k<= N;k++ )
    if(a[k].no==m)
   l=k;
 if(l!=0)
 {
   if(a[l].cha==1)
     a[l].cha=3;
  else if(a[l].cha==2)
    a[l].cha=4;
    else
    printf("Error!\n");
 }
 else
  printf("Error!");
}

void display()   //查看PCB功能模块
{
  int i;
  printf("\t\tPCB\tno\tko\tcha\n");
  for(i= 1;i<= 10;i++ )
  printf("\t\t%d\t%d\t%d\t%d\n",i,a[i].no,a[i].ko,a[i].cha);
  printf("\t1-静止就绪  2--静止阻塞  3--活动就绪  4--活动阻塞  5--执行\n");
}

void change_KO()   //改变优先数
{
  int k,m,l=0;
  printf("please input no0:");
  scanf("%d",&m);
  for(k= 1;k<= N;k++ )
    if(a[k].no==m)
   l=k;
    if(l!=0)
 {
     printf("please input new KO:");
     scanf("%d",&a[l].ko);
     display();
 }
 else
  printf("Error!");
}

int main()
{
  int i;

  do
  {
    printf("\t\t************** choice ***************\n");
    printf("\t\t*        1-----进程创建             *\n");
    printf("\t\t*        2-----进程撤消             *\n");
    printf("\t\t*        3-----调度                 *\n");
 printf("\t\t*        4-----阻塞                 *\n");
    printf("\t\t*        5-----唤醒                 *\n");
    printf("\t\t*        6-----挂起                 *\n");
    printf("\t\t*        7-----激活                 *\n");
    printf("\t\t*        8-----查看PCB功能模块      *\n");
    printf("\t\t*        9-----改变优先数           *\n");
     printf("\t\t*       10----查看进程             *\n");
    printf("\t\t*        0-----退出                 *\n");
    printf("\t\t*************************************\n");
    printf("\t\t请选择0-10:");
    scanf("%d",&i);
    printf("\n");
    switch(i)
    {
      case 1: create();break;
   case 2:stopproc();break;
   case 3: dispatch();break;
   case 4: block();break;
   case 5: wakeup();break;
   case 6: suspend();break;
   case 7: active();break;
   case 8: display();break;
   case 9: change_KO();break;
      case 10: showallproc();break;
   case 0: exit(0);   //程序正常退出
    }
  }
  while(i!=0);
}

 

(1)进程的软中断通信 #include #include #include #include int wait_flag; void stop(); main( ) { int pid1, pid2; // 定义两个进程号变量 signal(2,stop); // 或者 signal (14,stop); while((pid1 = fork( )) == -1); // 若创建子进程1不成功,则空循环 if(pid1 > 0) { // 子进程创建成功,pid1为进程号 while((pid2 = fork( )) == -1); // 创建子进程2 if(pid2 > 0) { wait_flag = 1; //sleep(1); // 父进程等待5秒 kill(pid1,SIGUSR1); // 杀死进程1 kill(pid2,SIGUSR2); // 杀死进程2 wait(0); wait(0); printf("\n Parent process is killed !!\n"); exit(0); // 父进程结束 } else { wait_flag = 1; signal(SIGUSR2,stop); // 等待进程2被杀死的中断号17 printf("\n Child process 2 is killed by parent !!\n"); exit(0); } } else { wait_flag = 1; signal(SIGUSR1,stop); // 等待进程1被杀死的中断号16 printf("\n Child process 1 is killed by parent !!\n"); exit(0); } } void stop() { wait_flag = 0; } (2)进程的管道通信 #include #include #include int pid1,pid2; // 定义两个进程变量 main( ) { int fd[2]; char OutPipe[100],InPipe[100]; // 定义两个字符数组 pipe(fd); // 创建管道 while((pid1 = fork( )) == -1); // 如果进程1创建不成功,则空循环 if(pid1 == 0) { lockf(fd[1],1,0); // 锁定管道 sprintf(OutPipe,"\n Child process 1 is sending message!\n"); write(fd[1],OutPipe,50); // 向管道写入数据 sleep(5); // 等待读进程读出数据 lockf(fd[1],0,0); // 解除管道的锁定 exit(0); // 结束进程1 } else { while((pid2 = fork()) == -1); // 若进程2创建不成功,则空循环 if(pid2 == 0) { lockf(fd[1],1,0); sprintf(OutPipe,"\n Child process 2 is sending message!\n"); write(fd[1],OutPipe,50); sleep(5); lockf(fd[1],0,0); exit(0); } else { wait(0); // 等待子进程1 结束 read(fd[0],InPipe,50); // 从管道中读出数据 printf("%s\n",InPipe); // 显示读出的数据 wait(0); // 等待子进程2 结束 read(fd[0],InPipe,50); printf("%s\n",InPipe); exit(0); // 父进程结束 } } }
操作系统 进程创建实验报告 调用fork( )创建子进程 实验原理: 一) 进程 UNIX中,进程既是一个独立拥有资源的基本单位,又是一个独立调度的基本单位。一个进程实体由若干个区(段)组成,包括程序区、数据区、栈区、共享存储区等。每个区又分为若干页,每个进程配置有唯一的进程控制块PCB,用于控制和管理进程。 PCB的数据结构如下: 1、进程表项(Process Table Entry)。包括一些最常用的核心数据: 进程标识符PID、用户标识符UID、进程状态、事件描述符、进程和U区在内存或外存的地址、软中断信号、计时域、进程的大小、偏置值nice、指向就绪队列中下一个PCB的指针P_Link、指向U区进程正文、数据及栈在内存区域的指针。 2、U区(U Area)。用于存放进程表项的一些扩充信息。 每一个进程都有一个私用的U区,其中含有:进程表项指针、真正用户标识符u-ruid(read user ID)、有效用户标识符u-euid(effective user ID)、用户文件描述符表、计时器、内部I/O参数、限制字段、差错字段、返回值、信号处理数组。 由于UNIX系统采用段页式存储管理,为了把段的起始虚地址变换为段在系统中的物理地址,便于实现区的共享,所以还有: 3、系统区表项。以存放各个段在物理存储器中的位置等信息。 系统把一个进程的虚地址空间划分为若干个连续的逻辑区,有正文区、数据区、栈区等。这些区是可被共享和保护的独立实体,多个进程可共享一个区。为了对区进行管理,核心中设置一个系统区表,各表项中记录了以下有关描述活动区的信息: 区的类型和大小、区的状态、区在物理存储器中的位置、引用计数、指向文件索引结点的指针。 4、进程区表 系统为每个进程配置了一张进程区表。表中,每一项记录一个区的起始虚地址及指向系统区表中对应的区表项。核心通过查找进程区表和系统区表,便可将区的逻辑地址变换为物理地址。 二) 进程映像 UNIX系统中,进程进程映像的执行过程,也就是正在执行的进程实体。它由三部分组成: 1、用户级上、下文。主要成分是用户程序; 2、寄存器上、下文。由CPU中的一些寄存器的内容组成,如PC,PSW,SP及通用寄存器等; 3、系统级上、下文。包括OS为管理进程所用的信息,有静态和动态之分。 三) 所涉及的系统调用 1、fork( ) 创建一个新进程。 系统调用格式: pid = fork( ) 参数定义: int fork( ) fork( )返回值意义如下: 0:在子进程中,pid变量保存的fork( )返回值为0,表示当前进程是子进程。 >0:在父进程中,pid变量保存的fork( )返回值为子进程的id值(进程唯一标识符)。 -1:创建失败。 如果fork( )调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork( )被调用了一次,但返回了两次。此时OS在内存中建立一个新进程,所建的新进程是调用fork( )进程(parent process)的副本,称为子进程(child process)。子进程继承了父进程的许多特性,并具有与父进程完全相同的用户级上下文。父进程与子进程并发执行。 核心为fork( )完成以下操作: (1)为新进程分配一进程表项和进程标识符 进入fork( )后,核心检查系统是否有足够的资源来建立一个新进程。若资源不足,则fork( )系统调用失败;否则,核心为新进程分配一进程表项和唯一的进程标识符。 (2)检查同时运行的进程数目 超过预先规定的最大数目时,fork( )系统调用失败。 (3)拷贝进程表项中的数据 将父进程的当前目录和所有已打开的数据拷贝到子进程表项中,并置进程的状态为“创建”状态。 (4)子进程继承父进程的所有文件 对父进程当前目录和所有已打开的文件表项中的引用计数加1。 (5)为子进程创建进程上、下文 进程创建结束,设子进程状态为“内存中就绪”并返回子进程的标识符。 (6)子进程执行 虽然父进程与子进程程序完全相同,但每个进程都有自己的程序计数器PC(注意子进程的PC开始位置),然后根据pid变量保存的fork( )返回值的不同,执行了不同的分支语句。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值