Linux:进程间通信IPC:管道

管道
有名管道

有名管道可以在任意两个进程之间通信

有名管道的创建:

  • 命令创建: mkfifo FIFO
  • 系统调用创建
#include <sys/types.h>
#include <sys/stat.h>
//filename 是管道名 mode 是创建的文件访问权限
int mkfifo(const char *filename, mode_t mode);

在a.c上写数据在b.c上读数据,在两个窗口运行两个程序,一个写数据,另一个同步读出数据

a.c写文件

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
int main()
{
    int fd=open("FIFO",O_WRONLY);
    printf("fd=%d\n",fd);
    while(1)
    {
        printf("input:");
        char buff[128]={0};
        fgets(buff,128,stdin);
        if(strncmp(buff,"end",3)==0)
        {
            break;
        }
        write(fd,buff,strlen(buff));
    }
    close(fd);
    exit(0);
}

b.c读文件

#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
int main()
{
    int fd=open("FIFO",O_RDONLY);
    printf("fd=%d",fd);
    while(1)
    { 
      char buff[128]={0};
      int n=read(fd,buff,127);//n是读到的字符数
      if(n==0)
      {
          break;
      }
      printf("n=%d,buff=%s\n",n,buff);
    }
    close(fd);
      exit(0);
}

管道写端关闭,读端会返回0

管道读端关闭,写端也会被关闭,会向写端发送终止信号

1.必须被两个进程同时打开,必须是一读一写,否则会被阻塞

2.打开管道open

3.写入数据write,管道文件存放在内存中,在磁盘上大小为0 管道数据如果为满会阻塞住

4.读管道 read 管道数据如果为空会阻塞住

5.关闭管道 close

无名管道

无名管道主要应用于父子进程间的通信

#include <unistd.h>
/*
pipe()成功返回 0,失败返回-1
fds[0]是管道读端的描述符      相当于文件的头指针
fds[1]是管道写端的描述符      相当于文件的尾指针
*/
int pipe(int fds[2]);

main文件,父子进程创建管道

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
int main()
{
    int fd[2];
    pipe(fd);//fd[0]读  fd[1] 写
    pid_t pid=fork();
    assert(pid!=-1);
    if(pid==0)
    {
        close(fd[1]);
        while(1)
        {
            char buff[128]={0};
            if(read(fd[0],buff,127)==0)
            {
                break;
            }
            else
            {
                printf("child read:%s\n",buff);
            }
        }
        close(fd[0]);
    }
    else
    {
        close(fd[0]);
        while(1)
        {
            char buff[128]={0};
            fgets(buff,128,stdin);
            if(strncmp(buff,"end",3)==0)
            {
                break;
            }
            else
            {
                write(fd[1],buff,strlen(buff));
            }

        }
        close(fd[1]);

    }
    exit(0);
}

管道的实现:
在这里插入图片描述

1.有名和无名的区别:

有名可以在任意两个进程间通信,无名只能用在父子进程

2.写入管道的数据在哪:

内存

3.管道通信的方式是全双工还是半双工:

半双工

通过dup2函数,更改子进程的输出方式

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>
int main()//更改子进程的输出方式,父进程将子进程的输出打入file.txt的文件中,或者打到屏幕上
{
    int fd[2];
    if(pipe(fd)==-1)//创建无名管道文件
    {
        exit(0);
    }
    pid_t pid=fork();
    if(pid==-1)
    {
        exit(0);
    }
    if(pid==0)
    {
        dup2(fd[1],1);//替换标准输出  输出到fd[1]中,覆盖掉1
        dup2(fd[1],2);//替换标准错误输出
        execl("/usr/bin/ps","ps","-f",(char*)0);
        printf("exec err");
        exit(0);
    }
    char buff[1024]={0};
    close(fd[1]);
    int n= read(fd[0],buff,1023);
    //printf("ps输出%s\n",buff);
    
    int fdw=open("file.txt",O_WRONLY|O_CREAT,0600);
    write(fdw,buff,strlen(buff));
    close(fd[0]);
    exit(0);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小新 蜡笔

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

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

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

打赏作者

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

抵扣说明:

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

余额充值