进程通信的三种方式(管道、消息缓冲队列、共享缓冲区)

操作系统实验导航
实验一:银行家算法 https://blog.youkuaiyun.com/weixin_46291251/article/details/115384510
实验二:多级队列调度和多级反馈队列调度算法 https://blog.youkuaiyun.com/weixin_46291251/article/details/115530582
实验三:动态分区式内存管理 https://blog.youkuaiyun.com/weixin_46291251/article/details/115772341
实验四:Linux下多进程通信 https://blog.youkuaiyun.com/weixin_46291251/article/details/116274665
实验五:进程通信的三种方式 https://blog.youkuaiyun.com/weixin_46291251/article/details/116301250
实验六:Linux文件系统实验 https://blog.youkuaiyun.com/weixin_46291251/article/details/116423798
实验七:自制简单U盘引导程序 https://blog.youkuaiyun.com/weixin_46291251/article/details/116427629
实验八:磁盘调度算法 https://blog.youkuaiyun.com/weixin_46291251/article/details/116431907
实验九:请求分页系统中的置换算法 https://blog.youkuaiyun.com/weixin_46291251/article/details/116443021
学习笔记:操作系统复习笔记 https://blog.youkuaiyun.com/weixin_46291251/article/details/117086851

背景:(关于进程通信的几种方式)

题目描述:

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

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

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

  3. 使用消息缓冲队列来实现 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。

算法设计:

管道:

对管道的设计类似于上一篇文章:Linux下两个子进程通过管道(pipe)通信

共享缓冲区:

共享内存是操作系统常采用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种通信方式需要依靠某种同步机制,如互斥锁和信号量等。

共享内存通过系统调用 shmget()、shmat()、shmdt()、shmctl()来实现.
  • 系统调用:shmget()
    原型:int shmget(key_t key, int size, int shmflg)
    参数:
    Key:共享存储区的名字;
    Size:共享存储区的大小(以字节计);
    Shmflag:用户设置的标志,如 IPC_CREAT,IPC_CREAT 表示若系统中尚无指名的共享存储区,则由核心建立一个共享存储区;如系统中已有共享存储区,便忽略 IPC_CREAT。
    返回值:
    成功返回共享内存的标识符;不成功返回-1
  • 系统调用:shmat()
    原型:void* shmat(int shmid, const void *shmaddr, int shmflg);
    参数:
    Shmid:共享存储区的标识符;
    Shmaddr:用户给定的,将共享存储区附接到进程的虚拟地址空间;
    Shmflg:规定共享存储区的读、写权限,以及系统是否应对用户规定的地址做舍入操作。其值为 SHM_RDONLY 时,表示只能读,其值为 0 时,表示可读、可写,其值为 SHM_RND(取整)时,表示操作系统在必要时舍去这个地址。返回值:
    该系统调用的返回值为共享存储区所附接到的进程虚地址。
  • 系统调用:shmdt()
    原型:int shmdt(void *shmaddr)参数:
    Shmaddr:要断开连接的虚地址,亦即以前由连接的系统调用 shmat()所返回的虚地址。
    返回值:
    调用成功时,返回 0 值,调用不成功,返回-1 值。
  • 系统调用:shmctl()
    原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    参数:
    Shmid:由 shmget 所返回的标识符;
    Cmd:是操作命令,可以分多种类型:
    (1)用于查询有关共享存储区的情况。如其长度、当前连接的进程数、共享区的创建者标识符。
    (2)用于设置或改变共享存储区的属性,如共享存储区的许可权、当前连接的进程计数等。
    (3)对共享存储区的加锁和解锁命令。
    (4)删除共享存储区标识符等。
    Buf:用户缓冲区地址。返回值:
    调用成功则返回 0,如果失败则返回-1。
创建共享缓冲区并等待被写入,然后读取:
//共享存储区
        shmid=shmget(SHMKEY,512,0777|IPC_CREAT); /*创建共享存储区*/
        printf("进程%d创建了共享存储区:\n",getpid());
        addr=shmat(shmid,0,0);        /*获取首地址*/
        *addr=-1;
        while (*addr == -1);//阻塞,用于进程同步
        printf("进程%d读取共享存储区:%d\n",getpid(),*addr);
   
等待共享缓冲区被创建,然后写入:
 //共享存储区
        shmid=shmget(SHMKEY,512,0777);      /*打开共享存储区*/
        addr=shmat(shmid,0,0);           /*获得共享存储区首地址*/
        while(*addr != -1);//阻塞,用于进程同步
        
        int xie = getpid();
        printf("进程%d写入共享存储区:%d\n",getpid(),xie);
        *addr= xie;

消息缓冲队列:

自定义消息数据结构:
struct msgform  //消息结构
{
   
   
   long mtype
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheney822

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值