无名管道-----实现父子进程相互通信

简介: 无名管道-----实现父子进程相互通信

创建一条无名管道并且给你两个文件描述符(读写的文件描述符)

pipefd[0]:读端

pipefd[1]:写端


思路:

只需要一个.c即可,fork一次即可(因为用的是无名管道)

注意:

父进程:

发:scanf + write //你好我是旦丁

收:read + printf //卡住

子进程:

发:scanf《卡》 + write “我不是旦丁”

收:read《卡》 + printf

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    //创建两个无名管道
    int pipefd1[2] = {0};
    int pipefd2[2] = {0};
    int pipe_father = pipe(pipefd1);
    int pipe_son = pipe(pipefd2);

    pid_t ret = fork(); //创建进程
    if (ret == -1)
    {
        perror("fork");
    }
    else if (ret == 0) //子进程
    {
        char msg_son[32] = {0};
        char msg_father[32] = {0};
        while (1)
        {
            memset(msg_father, 0, 32);
            read(pipefd2[0], msg_father, 32);   //读阻塞,当管道没有数据时,对管道进行读取会阻塞
            printf("父亲说:%s\n", msg_father);
            
            printf("儿子:");
            scanf("%s", msg_son);
            write(pipefd1[1], msg_son, strlen(msg_son));
        }
        close(pipefd1[1]);
        close(pipefd2[0]);
    }
    else //父进程
    {
        char msg_father[32] = {0};
        char msg_son[32] = {0};
        while (1)
        {
            printf("父亲:");
            scanf("%s", msg_father);
            write(pipefd2[1], msg_father, strlen(msg_father));

            memset(msg_son, 0, 32);
            read(pipefd1[0], msg_son, 32);
            printf("儿子说:%s\n", msg_son);
        }

        close(pipefd2[1]);
        close(pipefd1[0]);
        wait(NULL);
    }
    return 0;
}


代码实现效果:

代码优化:

一、一定要先确定谁先发,谁先收(父进程先发,子进程先收)。

二、.

第一通信:父进程先发,子进程先收

第二通信:

1)父进程先发,子进程先收

我是旦丁

(1:父进程想继续说,子进程继续收 0:父进程不想说了,子进程就可以说了 q:退出)

    2)子进程先发,父进程先收
    3)结束聊天
三、
  close

注意:

子进程和父进程的读写端同一个管道。

简单的避免自己发的信息不要被接受,发送之后可以sleep一下,让别人去接受。

#include <stdio.h>
#include <stdlib.h>//exit
#include <string.h>//memset
#include <errno.h>
#include <sys/types.h>//fork
#include <sys/wait.h>//wait
#include <unistd.h>//fork pipe

#define MSG_LENGTH  20

int main()
{

    int pipefd[2];
    int pipe_ret = pipe(pipefd);
    if(pipe_ret == -1)
    {
        perror("pipe");
        exit(-1);
    }

    int pid = fork();
    if(pid == -1)
    {
        perror("fork");
        exit(-1);
    }
    else if(pid == 0)
    {
        char spreak_mask = '1';//0:父进程不想说话 1:父进程想说话
        char msg_data[MSG_LENGTH];
        while(1)
        {
            memset(msg_data,0,MSG_LENGTH);
            if(spreak_mask == '0')
            {
                printf("请输入要发送给父进程的消息:");//hello
                scanf("%s",msg_data);//我司旦丁
                spreak_mask = msg_data[strlen(msg_data)-1];//更新密令
                write(pipefd[1],msg_data,strlen(msg_data));//write
                
                sleep(1);
            }
            else if(spreak_mask == '1')
            {
                //read
                read(pipefd[0],msg_data,MSG_LENGTH);
                spreak_mask = msg_data[strlen(msg_data)-1];//更新密令
                printf("父进程说:%s\n",msg_data);
            }
            else if(spreak_mask == 'q')
            {
                break;
            }
            else
            {
                printf("数据有误,终止通信!\n");
                exit(-1);
            }
        }

    }
    else
    {
        char spreak_mask = '1';//0:父进程不想说话 1:父进程想说话
        char msg_data[MSG_LENGTH];
        while(1)
        {
            memset(msg_data,0,MSG_LENGTH);
            if(spreak_mask == '0')
            {
                //read
                read(pipefd[0],msg_data,MSG_LENGTH);
                spreak_mask = msg_data[strlen(msg_data)-1];//更新密令
                printf("子进程说:%s\n",msg_data);
            }
            else if(spreak_mask == '1')
            {
                //write

                printf("请输入要发送给子进程的消息:");
                scanf("%s",msg_data);
                spreak_mask = msg_data[strlen(msg_data)-1];//更新密令
                write(pipefd[1],msg_data,strlen(msg_data));//write
                sleep(1);
            }
            else if(spreak_mask == 'q')
            {
                break;
            }
            else
            {
                printf("数据有误,终止通信!\n");
                exit(-1);
            }
        }
    }

    /*共享区域*/
    close(pipefd[0]);
    close(pipefd[1]);

    if(pid>0)
    {
        wait(NULL);
    }
    exit(0);
}


相关文章
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
2087 14
|
消息中间件 存储 供应链
进程间通信方式-----消息队列通信
【10月更文挑战第29天】消息队列通信是一种强大而灵活的进程间通信机制,它通过异步通信、解耦和缓冲等特性,为分布式系统和多进程应用提供了高效的通信方式。在实际应用中,需要根据具体的需求和场景,合理地选择和使用消息队列,以充分发挥其优势,同时注意其可能带来的复杂性和性能开销等问题。
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
388 16
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
1128 4
|
消息中间件 Unix Linux
C语言 多进程编程(二)管道
本文详细介绍了Linux下的进程间通信(IPC),重点讨论了管道通信机制。首先,文章概述了进程间通信的基本概念及重要性,并列举了几种常见的IPC方式。接着深入探讨了管道通信,包括无名管道(匿名管道)和有名管道(命名管道)。无名管道主要用于父子进程间的单向通信,有名管道则可用于任意进程间的通信。文中提供了丰富的示例代码,展示了如何使用`pipe()`和`mkfifo()`函数创建管道,并通过实例演示了如何利用管道进行进程间的消息传递。此外,还分析了管道的特点、优缺点以及如何通过`errno`判断管道是否存在,帮助读者更好地理解和应用管道通信技术。
|
存储 Python
Python中的多进程通信实践指南
Python中的多进程通信实践指南
315 0
|
SQL 网络协议 数据库连接
已解决:连接SqlServer出现 provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程【C#连接SqlServer踩坑记录】
本文介绍了解决连接SqlServer时出现“provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程”错误的步骤,包括更改服务器验证模式、修改sa用户设置、启用TCP/IP协议,以及检查数据库连接语句中的实例名是否正确。此外,还解释了实例名mssqlserver和sqlserver之间的区别,包括它们在默认设置、功能和用途上的差异。
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
425 0
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。

热门文章

最新文章