首页 > 系统相关 >两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束

两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束

时间:2024-09-04 22:51:52浏览次数:6  
标签:include flag 循环 key 进程 共享内存 buf 输入

目录

题目

思路

实现:

input.c

output.c


题目

两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束

这两个标志在两个进程里,是不共享的,所以为了共享标志位可以和buf封装到一个结构体里作为共享内存。

struct msg

{

int flag;

char buf[32];

};

思路

一、整体功能概述

 

这段代码通过共享内存实现了两个进程之间的通信。一个进程负责从终端接收输入,另一个进程负责循环打印输入的内容,当输入为 “quit” 时,两个进程都结束。

 

二、结构体定义与共享内存的作用

 
  1. 定义了一个结构体 struct msg,包含一个标志位 flag 和一个字符数组 buf[32]。这个结构体将用于存储输入的字符串和一个标志,以协调两个进程的操作。
  2. 通过共享内存,两个进程可以访问同一块内存区域,即这个结构体。这样就实现了在不同进程之间共享数据的目的。
 

三、input 进程分析

 
  1. 生成共享内存键值

    • 使用 ftok 函数以指定的文件("shm.c")和字符('a')生成一个唯一的键值 key。如果生成键值失败,输出错误信息并返回 -1
  2. 创建或打开共享内存

    • 使用 shmget 函数尝试创建一个新的共享内存段。如果共享内存已经存在(errno == EEXIST),则打开已有的共享内存。如果创建或打开共享内存失败,输出错误信息并返回 -1
  3. 映射共享内存

    • 使用 shmat 函数将共享内存映射到进程的地址空间。如果映射失败,输出错误信息并返回 -1
  4. 输入循环

    • 在一个无限循环中,当标志位 flag 为 0 时,从终端读取输入并存储到 buf 中,然后将标志位设置为 1。
    • 如果输入的字符串是 “quit”,则退出循环。
  5. 取消映射和删除共享内存(可选)

    • 使用 shmdt 函数取消共享内存的映射。
    • 可以选择使用 shmctl 函数删除共享内存,但在代码中被注释掉了。
 

四、output 进程分析

 
  1. 与 input 进程类似的步骤生成键值、创建或打开共享内存以及映射共享内存。

  2. 输出循环

    • 在一个无限循环中,检查输入的字符串是否为 “quit”,如果是则退出循环。
    • 当标志位 flag 为 1 时,打印存储在 buf 中的字符串,然后将标志位设置为 0。
  3. 与 input 进程类似的取消映射和删除共享内存(可选)步骤。

 

五、总体执行流程分析

 
  1. 分别运行 input 和 output 两个程序,它们会生成相同的键值,从而可以访问同一块共享内存。
  2. input 进程等待用户输入,并将输入存储在共享内存中,设置标志位表示有新的输入。
  3. output 进程不断检查共享内存中的标志位和输入内容,如果有新的输入则打印出来,并重置标志位。
  4. 当 input 进程输入 “quit” 时,两个进程都会检测到这个字符串并退出循环,然后可以选择删除共享内存以释放系统资源。
 

六、应用场景和注意事项

 
  1. 应用场景:

    • 适用于需要在不同进程之间进行数据交互的场景,尤其是当数据量较大或者需要频繁通信时,共享内存可以提供高效的通信方式。
    • 可以用于实现分布式系统中的数据共享和协调。
  2. 注意事项:

    • 确保在使用共享内存时进行适当的同步和互斥操作,以避免数据竞争和不一致性。这里的标志位可以起到一定的同步作用,但在更复杂的场景中可能需要使用信号量等同步机制。
    • 注意在程序结束时正确地取消映射和删除共享内存,以避免资源泄漏。
    • 考虑共享内存的大小限制,避免存储过多的数据导致内存溢出。

实现:

input.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h>

struct msg
{
    int flag;
    char buf[32];
};

int main(int argc, char const *argv[])
{
    int shmid;
    key_t key;
    struct msg *p;
    key = ftok("shm.c", 'a');
    if (key < 0)
    {
        perror("key err");
        return -1;
    }
    printf("key: %#x\n", key);

    //打开或创建共享内存
    shmid = shmget(key, sizeof(struct msg), IPC_CREAT | IPC_EXCL | 0777); //如果共享内存不存在则创建,存在则返回-1
    if (shmid <= 0)
    {
        if (errno == EEXIST)                               //如果共享内存已存在则,直接打开
            shmid = shmget(key, sizeof(struct msg), 0777); //直接打开已有的共享内存并且获得共享内存id
        else
        {
            perror("shmget err");
            return -1;
        }
    }
    printf("shmid: %d\n", shmid);

    //映射共享内存
    p = (struct msg *)shmat(shmid, NULL, 0);
    if (p == (struct msg *)-1)
    {
        perror("shmat err");
        return -1;
    }

    p->flag = 0;
    while (1)
    {
        if (strcmp(p->buf, "quit") == 0)
            break;
        if (p->flag == 1)
        {
            printf("%s\n", p->buf);
            p->flag = 0;
        }
    }

    //取消映射
    shmdt(p);

    //删除共享内存
    //shmctl(shmid,IPC_RMID,NULL);

    return 0;
}

output.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h>

struct msg
{
    int flag;
    char buf[32];
};

int main(int argc, char const *argv[])
{
    int shmid;
    key_t key;
    struct msg *p;
    key = ftok("shm.c", 'a');
    if (key < 0)
    {
        perror("key err");
        return -1;
    }
    printf("key: %#x\n", key);

    //打开或创建共享内存
    shmid = shmget(key, sizeof(struct msg), IPC_CREAT | IPC_EXCL | 0777); //如果共享内存不存在则创建,存在则返回-1
    if (shmid <= 0)
    {
        if (errno == EEXIST)                               //如果共享内存已存在则,直接打开
            shmid = shmget(key, sizeof(struct msg), 0777); //直接打开已有的共享内存并且获得共享内存id
        else
        {
            perror("shmget err");
            return -1;
        }
    }
    printf("shmid: %d\n", shmid);

    //映射共享内存
    p = (struct msg *)shmat(shmid, NULL, 0);
    if (p == (struct msg *)-1)
    {
        perror("shmat err");
        return -1;
    }

    p->flag = 0;
    while (1)
    {
        if (strcmp(p->buf, "quit") == 0)
            break;
        if (p->flag == 1)
        {
            printf("%s\n", p->buf);
            p->flag = 0;
        }
    }

    //取消映射
    shmdt(p);

    //删除共享内存
    //shmctl(shmid,IPC_RMID,NULL);

    return 0;
}

标签:include,flag,循环,key,进程,共享内存,buf,输入
From: https://blog.csdn.net/QR70892/article/details/141906378

相关文章

  • Python监控进程资源占用并发送邮件
    项目新特性上线后,有时会因为包含内存泄露的问题导致服务资源被占满,以至于线上服务崩溃。最简单的方式是对服务期CPU/内存占用进行监测和及时预警。python中pyutil包是自动化运维常用的工具库之一,可以进行方便获取服务器CPU/内存及进程等相关信息。安装方法pipinstallpsutil......
  • Linux 进程管理与负载
    1.进程管理1.1进程进程:process运行起来的命令或代码或程序.进程本质运行在内存中.cpu:处理内存:软件磁盘:永久存放数据.守护进程(服务):持续运行的进程.1.2僵尸进程⭐️⭐️⭐️⭐️⭐️1.2.1概述异常进程僵尸进程:进程因为一些原因脱离系统控制,但是进程又没有正常的退......
  • 【Linux】进程间的关系(第十三篇)
    目录1.亲缘关系:2.进程组关系:3.会话关系4.进程、进程组与会话的关系5.例子1.亲缘关系:2.进程组关系:3.进程间会话关系1.亲缘关系:多个进程间可能存在亲缘关系(多个进程间可能是父子进程结构,也可能更为复杂的层级亲缘结构)2.进程组关系:定义:进程组是一个或多个进程的集......
  • 【Linux】孤儿进程(第十二篇)
    目录孤儿进程定义产生原因处理机制特性与影响示例守护进程(daemon)定义:特点:与孤儿进程的区别:孤儿进程孤儿进程是操作系统中的一个概念,主要出现在类UNIX操作系统中。以下是关于孤儿进程的详细解释:定义孤儿进程指的是在其父进程执行完成或被终止后,仍继续运行的......
  • 【机器学习-神经网络】循环神经网络
    【作者主页】FrancekChen【专栏介绍】⌈⌈⌈Python机器学习⌋......
  • Android开机流程-从Init进程启动到进入Android桌面
    1.init进程启动流程Androidbootloader负责加载boot.img,将其内容放入内存,然后启动内核。内核接管之后,会解压并加载ramdisk到内存中,然后启动用户空间的第一个进程init。在Android系统启动过程中,ramdisk.img被内核直接解压到内存中并用作初始根文件系统。这一过程不是通过......
  • PC电源,USB Type-C通用型双向同步升降压控制器支持5V驱动可编程输出输入电流限制
    概述:PC1045是一款同步升降压控制器,适用于驱动高效电源转换器中的MOSFET或氮化镓(GaN)等功率器件。它支持高达45V的宽输入和输出电压范围,并可在降压、升降压和升压模式之间无缝转换。PC1045集成了具有UVLO保护功能的上管和下管栅极驱动器。它提供可编程电感峰值电流限制和输......
  • 多云复杂性正在危及组织的数字化进程
    对于追求数字化转型的企业和公共部门领导者来说,云计算在某种程度上是一种矛盾。 一方面,云是一种无处不在的推动因素,被视为实现任何转型议程的关键组成部分,但研究表明,它引入了运营复杂性,以至于难以提供出色的数字化客户体验。 因此,它同时简化了数字体验的交付,同时也使其复杂化。当......
  • 编程新手必看:探索编程中的 for 循环20 种语言的实践与比较
    在这里我展示了20多种编程语言中的for循环实现。希望这些示例对大家学习不同语言的语法有帮助!1.C语言2.C++3.Python4.JavaScript5.Java6.Ruby7.Swift8.Go9.Rust10.Kotlin11.PHP12.TypeScript13.Perl14.Haskell15.Scala16.Julia17.R18.MATLAB19.Lua......
  • 进程间通信——消息队列(通俗易懂)
    消息队列概念消息队列是消息的链表,存放在内核中并由消息队列标识符标识,消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺陷。消息队列包括POSIX消息队列和SystemV消息队列。消息队列是UNIX下不同进程之间实现共享资源的一种机制,UNIX......