进程间通信之管道

本文深入探讨了进程间通信(IPC)中的两种主要形式:管道和FIFO(有名管道)。首先介绍了管道的工作原理、特点及局限性,并通过示例代码展示了如何在父子进程中使用管道进行数据交换。接着详细讨论了FIFO的特性及其应用场景,提供了使用FIFO进行无血缘关系进程间通信的具体实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程间通信之管道


一、管道的概念
1.本质
(1)内核缓存区
(2)伪文件——不占用磁盘空间
2.特点
(1)两部分:
(2)读端,写端,对应两个文件描述符
(3)数据写端流入,读端流出
(4)操作管道的进程被销毁之后,管道自动释放
(5)管道默认阻塞的
3.管道的原理
1.内部实现的方式:队列
环形队列
特点:先进先出
缓冲区大小:
- 默认4K
- 大小会根据实际情况进程调整
4.管道的局限性
队列:数据只能读取一次,不能重复读取
半双工
匿名管道,适用于有血缘关系的进程
5.创建匿名管道:
int pipe(int fd[2])
fd 传出参数
fd[0]-读端
fd[1]-写端
6.父子进程使用管道进行通信
通信的步骤:
1.创建子进程
2.关闭子进程读端,关闭父进程的写端
这里写图片描述
代码

 1 #include"utili.h"                                                                                       
  2 
  3 int main()
  4 {
  5     int fd[2];
  6     pid_t pid;
  7     int res = pipe(fd);
  8     if(res < 0)
  9     {
 10         printf("error\n");
 11         return 1;
 12     }
 13     pid = fork();
 14     if(pid < 0 )
 15     {
 16         printf("error\n");
 17     }
 18     else if(pid == 0)
 19     {
 20         close(fd[0]);
 21         write(fd[1],"hello world\n",12);
 22     }
 23     else
 24     {
 25         close(fd[1]);
 26         char buff[100];
 27         int len = read(fd[0],buff,12);
 28         printf("%s\n",buff);
 29         wait(NULL);
 30     }
 31     return 0;
 32 }                

结果:

wz@wz-machine:~/linux/pipe$ gcc pipe3.c -o pipe3
wz@wz-machine:~/linux/pipe$ ./pipe3
hello world

二、FIFO(有名管道)
1.特点

  • 有名管道
  • 伪文件,在磁盘大小永远为0
  • 在内核对应有一个缓冲区
  • 半双工的通信方式

    2.使用场景

  • 没有血缘关系的进程间通信
    3.创建方法

  • 命令:mkfifo 管道名

  • 函数:mkfifo
    4.fifo文件可以使用I/O函数进行操作

  • open/close

  • read/write
  • 不能执行lseek操作
    5.进程间通信(代码)
    cli.c
    “`
    #include”../utili.h”

void SendData(int write_fd);
void RecvData(int read_fd);

int main()
{
//int read_fd;
int read_fd = open(write_fifo, O_RDONLY);
if(read_fd == -1)
{
perror(“open”);
return -1;
}

if(access(read_fifo, F_OK) == -1)
{
    int res = mkfifo(read_fifo, O_CREAT|O_EXCL|0755);
    if(res != 0)
    {
        perror("mkfifo");
        return -1;
    }
}
int write_fd = open(read_fifo, O_WRONLY);
if(write_fd == -1)
{
    perror("open read fifo");
    unlink(read_fifo);
    return -1;
}

pid_t pid;
pid = fork();
if(pid == 0)
{
    SendData(write_fd);
    exit(0);
}
else if(pid > 0)
{
    RecvData(read_fd);
    int status;
    wait(&status);
}
else
{
    perror("fork");
}

if 0

char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while(1)
{
    read(read_fd, recvbuf, BUFFER_SIZE);
    printf("Ser:> %s\n",recvbuf);
    printf("Cli:>");
    scanf("%s",sendbuf);
    if(strncmp(sendbuf, "quit", 4) == 0)
        break;
    write(write_fd, sendbuf, strlen(sendbuf)+1);
}

endif

unlink(read_fifo);
return 0;

}

void SendData(int write_fd)
{
char sendbuf[BUFFER_SIZE];
while(1)
{
printf(“Cli:>”);
scanf(“%s”, sendbuf);
if(strncmp(sendbuf, “quit”, 4) == 0)
break;
write(write_fd, sendbuf, strlen(sendbuf)+1);
}
}
void RecvData(int read_fd)
{
char recvbuf[BUFFER_SIZE];
while(1)
{
read(read_fd, recvbuf, BUFFER_SIZE);
printf(“Ser:> %s\n”,recvbuf);
}
}


cli.c

#include”../utili.h”

void SendData(int write_fd);
void RecvData(int read_fd);

int main(int argc, char *argv[])
{
if(access(write_fifo, F_OK) == -1)
{
int res = mkfifo(write_fifo, O_CREAT|O_EXCL|0755);
if(res != 0)
{
perror(“mkfifo”);
return -1;
};
}

printf("Server Wait Client Connect.......\n");
int write_fd; //  fd[1]
write_fd = open(write_fifo, O_WRONLY|O_NONBLOCK);
if(write_fd == -1)
{
    perror("poen write_fifo");
    unlink(write_fifo);
    return -1;
}

int read_fd;
while((read_fd = open(read_fifo, O_RDONLY)) == -1)
{
    sleep(1);
}
printf("Client Connect Server OK.\n");

//char sendbuf[BUFFER_SIZE];
//char recvbuf[BUFFER_SIZE];

pid_t pid;
pid = fork();
if(pid == 0)
{
    SendData(write_fd);
    exit(0);
}
else if(pid > 0)
{
    RecvData(read_fd);
    int status;
    wait(&status);
}
else
{
    perror("fork");
}

if 0

while(1)
{
    printf("Ser:>");
    scanf("%s",sendbuf);
    if(strncmp(sendbuf, "quit", 4) == 0)
        break;
    write(write_fd, sendbuf, strlen(sendbuf)+1);

    read(read_fd, recvbuf, BUFFER_SIZE);
    printf("Cli:> %s\n",recvbuf);
}

endif

unlink(write_fifo);
return 0;

}

void SendData(int write_fd)
{
char sendbuf[BUFFER_SIZE];
while(1)
{
printf(“Ser:>”);
scanf(“%s”, sendbuf);
if(strncmp(sendbuf, “quit”, 4) == 0)
break;
write(write_fd, sendbuf, strlen(sendbuf)+1);
}
}
void RecvData(int read_fd)
{
char recvbuf[BUFFER_SIZE];
while(1)
{
read(read_fd, recvbuf, BUFFER_SIZE);
printf(“Cli:> %s\n”,recvbuf);
}
}

“`
utili.h

#pragma once

#include<iostream>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdlib.h>
using namespace std;

#define BUFFER_SIZE  256

const char *write_fifo = "write_fifo";
const char *read_fifo = "read_fifo";
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值