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

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

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

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);
}


相关文章
|
14天前
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
14天前
|
消息中间件 存储 供应链
进程间通信方式-----消息队列通信
【10月更文挑战第29天】消息队列通信是一种强大而灵活的进程间通信机制,它通过异步通信、解耦和缓冲等特性,为分布式系统和多进程应用提供了高效的通信方式。在实际应用中,需要根据具体的需求和场景,合理地选择和使用消息队列,以充分发挥其优势,同时注意其可能带来的复杂性和性能开销等问题。
|
1月前
|
存储 Python
Python中的多进程通信实践指南
Python中的多进程通信实践指南
20 0
|
2月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
312 4
|
2月前
|
消息中间件 Unix Linux
C语言 多进程编程(二)管道
本文详细介绍了Linux下的进程间通信(IPC),重点讨论了管道通信机制。首先,文章概述了进程间通信的基本概念及重要性,并列举了几种常见的IPC方式。接着深入探讨了管道通信,包括无名管道(匿名管道)和有名管道(命名管道)。无名管道主要用于父子进程间的单向通信,有名管道则可用于任意进程间的通信。文中提供了丰富的示例代码,展示了如何使用`pipe()`和`mkfifo()`函数创建管道,并通过实例演示了如何利用管道进行进程间的消息传递。此外,还分析了管道的特点、优缺点以及如何通过`errno`判断管道是否存在,帮助读者更好地理解和应用管道通信技术。
|
2月前
|
SQL 网络协议 数据库连接
已解决:连接SqlServer出现 provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程【C#连接SqlServer踩坑记录】
本文介绍了解决连接SqlServer时出现“provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程”错误的步骤,包括更改服务器验证模式、修改sa用户设置、启用TCP/IP协议,以及检查数据库连接语句中的实例名是否正确。此外,还解释了实例名mssqlserver和sqlserver之间的区别,包括它们在默认设置、功能和用途上的差异。
|
3月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
161 3
|
3月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
67 0
|
3月前
|
消息中间件 存储 安全
python多进程并发编程之互斥锁与进程间的通信
python多进程并发编程之互斥锁与进程间的通信
|
4月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能

热门文章

最新文章

相关实验场景

更多