操作系统课程设计六、进程通信

操作系统课程设计六、进程通信

实验内容

编写一程序可以由用户选择如下三种进程通信方式:

1.使用管道来实现父子进程之间的进程通信子进程向父进程发送自己的进程标识符,以及字符串“is sending a message to parent”。父进程则通过管道读出子进程发来的消息,将消息显示在屏幕上,然后终止。

2.使用消息缓冲队列来实现 client 进程和 server 进程之间的通信server 进程先建立一个关键字为 SVKEY(如 75)的消息队列,然后等待接收类型为 REQ(例如 1)的消息;在收到请求消息后,它便显示字符串“serving for client”和接收到的 client 进程的进程标识数,表示正在为 client 进程服务;然后再向 client 进程发送应答消息,该消息的类型是 client 进程的进程标识数,而正文则是 server 进程自己的标识ID。client 进程则向消息队列发送类型为 REQ 的消息(消息的正文为自己的进程标识 ID) 以取得 sever 进程的服务,并等待 server 进程发来的应答;然后显示字符串“receive reply from”和接收到的 server 进程的标识 ID。

3.使用共享存储区来实现两个进程之间的进程通信进程 A 创建一个长度为 512 字节的共享内存,并显示写入该共享内存的数据;进程 B 将共享内存附加到自己的地址空间,并向共享内存中写入数据。

实验功能及设计思路

程序功能:

提供三种进程通信方式,供用户选择。第一个是管道通信,子进程向父进程发送自己的进程标识符,以及字符串“is sending a message to parent”,父进程接受消息打印屏幕。第二个是消息缓冲队列实现,client 进程和 server 进程之间的通信传递消息。第三个是使用共享存储区来实现两个进程之间的进程通信,进程A创建共享内存,写入数据,进程 B添加到自己地址空间,写入数据。

设计思路:

1.主程序中设计一个菜单,提供用户三种进程通信的选择,每当用户选择其中一项,调用相关响应函数。

2.管道机制类似实验4中的处理。

3.消息队列:消息队列是消息的链接表,包括 Posix 消息队列 systemV 消息队列。它克服了另外两种通信方式中信息量有限的缺点,对消息队列具有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读取消息。消息队列通过系统调用 msgget()、msgsnd()、msgrcv()来实现,函数的功能和实现过程分别如下。

原型:int msgge(key_t key,int msgflg)  

4.共享内存:共享内存是操作系统常采用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种通信方式需要依靠某种同步机制,如互斥锁和信号量等。共享内存通过系统调用 shmget()、shmat()、shmdt()、shmctl()来实现,函数的功能和实现过程分别如下。

系统调用:shmget()    

原型:int  shmget(key_t key, int size, int shmflg)  

源代码

#include <iostream>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
using namespace std;
const int SIZE=1<<8;
struct msgp{
      long long mtype;
      char mtext[250];
}msg;
const int SVKEY=75;
int msgqid,pid,*pint,i;
void pipeComm()
{
    pid_t pid;
    int fd[2];
    char buf[SIZE];
    char msg[SIZE];
    memset(buf, 0, SIZE);
    memset(msg, 0, SIZE);
    if (pipe(fd) < 0)
    {
        perror("pipe");
        exit(1);
    }
    pid = fork();
    if (pid == 0)//子
    {
        close(fd[0]);
        sprintf(msg, "%d is sending a message to parent %d by PIPE\n", getpid(), getppid());
        write(fd[1], msg, strlen(msg));

        exit(0);
    }
    else if (pid > 0)
    {
        close(fd[1]);

        sleep(0);

        read(fd[0], buf, SIZE);
        printf("%s", buf);
    }
    else
    {
        perror("fork");
        exit(1);
    }
}
void client()
{
   msgqid=msgget(SVKEY,0777);  //打开 75#消息队列
   pid=getpid();  //获取client进程标识符
   pint=(int *)msg.mtext;  //把正文的内容传给 pint,并强制转换类型
   *pint=pid;  //pint指针指向client进程标识符
   msg.mtype=1;  //消息类型为 1
   msgsnd(msgqid,&msg,sizeof(int),0);  //发送消息msg入msgqid消息队列
   msgrcv(msgqid,&msg,250,pid,0);  //从队列msgqid接收消息msg
   printf("client:receive reply from pid of  %d\n",*pint);  //显示 server进程标识数
   exit(0);
}
void server()
{
   msgqid=msgget(SVKEY,0777|IPC_CREAT);  //创建 75#消息队列
   msgrcv(msgqid,&msg,250,1,0);  //接收client进程标识数消息
   pint=(int *)msg.mtext;  //把正文的内容传给 pint,并强制转换类型
   pid=*pint;  //获得 cilent 进程标识数
   printf("server::serving for client  pid  of %d\n",pid);
   msg.mtype=pid;  //消息类型为 client 进程标识数
   *pint=getpid();  //获取 server 进程标识数
   msgsnd(msgqid,&msg,sizeof(int),0);  //发送消息
   exit(0);
}
void msgQueueComm()
{
   i=fork();  //创建进程 1
   if(!i)server();
  i=fork(); //创建进程 2
   if(!i) client();
   sleep(1);
}
void sharedMemComm(){
    int id;
    char *addr;
    char message[512];
    id=shmget(75,512,0777|IPC_CREAT);
    if(fork()==0){
        sprintf(message,"%d is sending message to parent",getpid());
        printf("%s\n",message);
        addr=(char*)shmat(id,0,0);
        strcpy(addr,message);
        shmdt(addr);
     }else{
        //wait(0);
        addr=(char*)shmat(id,0,0);
        printf("%s\n",addr);
        shmdt(addr);
        shmctl(id,IPC_RMID,0);
      }
}
int main()
{
    cout<<"        进程通信程序        "<<endl;
    int choice;
    while(1)
    {
        cout<<"\n选择操作"<<endl;
        cout<<"1.管道通信"<<endl;
        cout<<"2.消息队列"<<endl;
        cout<<"3.共享储存区\n"<<endl;
        cin>>choice;
        switch (choice)
        {
        case 1:
            pipeComm();
            break;
        case 2:
            msgQueueComm();
            //wait(0);
            break;
        case 3:
            sharedMemComm();
            break;
        default:
            printf("INPUT ERROR!\n");
            break;
        }
        sleep(1);
    }
    return 0;
}

  • 6
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 武汉理工大学操作系统课程设计使用Java编程语言开展。在该课程设计中,学生将通过自主设计和实现一个操作系统的核心功能,来加深对操作系统原理的理解和应用。 针对操作系统的主要功能模块,学生将会学习与实践相关的Java知识和技术,包括多线程编程、进程管理、内存管理、文件系统实现等。通过使用Java语言进行实现,学生可以更加灵活地运用面向对象的编程思想和Java提供的丰富工具和类库,使得操作系统的设计更加模块化、可扩展和可维护。 在操作系统课程设计中,学生将会面临各种挑战和难题。例如,他们需要设计合适的线程调度算法来实现多任务处理的高效性;需要管理和分配内存空间,避免内存泄漏和碎片问题;需要设计和实现文件系统,支持文件的创建、读写和删除等操作。 通过操作系统课程设计,学生可以提高自己的编程能力和操作系统的理论知识。他们可以学习如何分析和解决复杂的问题,了解操作系统的底层工作原理,加深对计算机系统的理解。 总之,武汉理工大学操作系统课程设计使用Java开展,通过学生的自主设计和实现,以及对Java编程技术的应用,旨在提高学生对操作系统原理的理解和应用能力,培养他们的编程能力和解决问题的能力。这将为他们今后的学习和工作打下坚实的基础。 ### 回答2: 武汉理工大学操作系统课程设计中选择使用Java编写项目是因为Java是一种跨平台编程语言,具有良好的可移植性和兼容性。由于操作系统涉及底层资源的管理和调度,对于编程语言的要求较高,而Java具有面向对象的设计思想,能够较好地结合操作系统的需求进行编程设计。 在操作系统课程设计中,Java可以很好地支持多线程和进程调度的实现。多线程是操作系统中常用的技术,能够提高程序的并发性和响应速度。通过Java提供的线程库,可以方便地创建和管理多个线程,并实现线程间的同步和通信,从而使程序的并发执行能力得到提升。 此外,Java还具有良好的异常处理机制,能够有效地处理操作系统中可能出现的各种错误和异常情况。操作系统中往往存在各种类型的资源冲突和竞争,因此对于错误处理和异常处理的能力要求较高。Java的异常处理机制能够帮助开发者更好地应对这些问题,并提供相应的错误提示和处理方式。 此外,Java还具有较为完善的标准库和第三方库,为操作系统课程设计提供了丰富的开发资源和工具。可以利用Java的网络编程库,实现操作系统之间的通信和数据交换。同时,借助Java提供的数据结构和算法库,可以更加高效地设计和实现操作系统中的各种数据结构和算法。 综上所述,武汉理工大学操作系统课程设计中选择使用Java作为开发语言,是出于其跨平台、多线程、异常处理和丰富的开发资源的优势。通过利用Java的特性和修炼软件工程的基本方法,可以更好地完成操作系统的设计与实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值