有名管道(Named Pipe / FIFO)

有名管道是一种有文件名的管道,允许无亲缘关系的进程进行通信。

特性 无名管道(Pipe) 有名管道(FIFO)
文件名 有(文件系统中的特殊文件)
通信范围 只能父子/兄弟进程 任意进程
创建方式 pipe() mkfifo()
打开方式 自动打开 需要用 open()
持久性 随进程结束消失 文件存在,可重复使用
可见性 不可见 在文件系统中可见
打开模式 行为
O_RDONLY 阻塞直到有进程以 O_WRONLY 打开
O_WRONLY 阻塞直到有进程以 O_RDONLY 打开
O_RDWR 不阻塞(但一般不推荐,会破坏管道意义)
O_NONBLOCK 非阻塞模式,立即返回

创建

#include "head.h"


int main(int argc,const char *argv[])
{
    int ret = mkfifo("pipe",0664);
    if(ret<0 && errno !=EEXIST)//错误码不是"文件已存在"
    //允许管道文件已经存在,不视为错误。
    {
        perror("mkfifo error");
        return -1;
    }

    int fd = open("pipe",O_WRONLY);
    if(fd<0)
    {
        perror("open error");
        return -1;
    }

    ssize_t size=write(fd,"hello world",11);
    printf("size=%ld\n",size);

    close(fd);
    return 0;
}
#include "head.h"


int main(int argc,const char *argv[])
{
    int ret = mkfifo("pipe",0664);
    if(ret<0 && errno !=EEXIST)
    {
        perror("mkfifo error");
        return -1;
    }

    int fd = open("pipe",O_RDONLY);
    if(fd<0)
    {
        perror("open error");
        return -1;
    }

    char buff[1024]={0};
    ssize_t size=read(fd,buff,sizeof(buff));
    printf("size=%ld,buff=%s\n",size,buff);

    close(fd);

    remove("pipe");
    return 0;
}
单工 只能一个方向 广播电台 电视、收音机
半双工 双向交替 对讲机 管道、I2C
全双工 双向同时 电话 网线、SPI

半双工式对话

#include <stdio.h>
#include "head.h"

int main(int argc, const char *argv[])
{
  int ret1 = mkfifo("pipe1", 0664);
  int ret2 = mkfifo("pipe2", 0664);
  if (ret1 < 0 && ret2 < 0 && errno != EEXIST)
  {
    perror("mkfifo error");
    return -1;
  }

  char buff[1024] = {0};
  int fd1 = open("pipe1", O_WRONLY);
  int fd2 = open("pipe2", O_RDONLY);
  while (1)
  {
    fgets(buff, sizeof(buff), stdin);
    write(fd1, buff, strlen(buff));

    memset(buff, 0, sizeof(buff));//将缓冲区 buff 的所有字节设置为 0
    //接收数据前清空缓冲区,防止残留数据干扰。
    //read 是二进制字节流读取函数,不知道也不关心数据是否是字符串,所以不会自动添加 \0
    ssize_t size = read(fd2, buff, sizeof(buff));
    printf("size = %ld,buff = %s\n", size, buff);
  }

  close(fd1);
  close(fd2);
  return 0;
}
#include"head.h"


int main(int argc,const char *argv[])
{
    int ret1 = mkfifo("pipe1",0664);
    int ret2 = mkfifo("pipe2",0664);
    if(ret1<0&&ret2<0&&errno!=EEXIST)
    {
        perror("mkfifo error");
        return -1;
    }

    char buff[1024]={0};
    int fd1=open("pipe1",O_RDONLY);
    int fd2=open("pipe2",O_WRONLY);

    while(1)
    {
        ssize_t size=read(fd1,buff,sizeof(buff));
        printf("size = %ld,buff = %s\n", size, buff);

        fgets(buff,sizeof(buff),stdin);
        write(fd2,buff,strlen(buff));
    }
    close(fd1);
    close(fd2);
    return 0;

}

全双工对话

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "head.h"

int main(int argc, const char *argv[])
{
  int ret1 = mkfifo("pipe3", 0664);
  int ret2 = mkfifo("pipe4", 0664);
  if (ret1 < 0 && ret2 < 0 && errno != EEXIST)
  {
    perror("mkfifo error");
    return -1;
  }

  char buff[1024] = {0};

  pid_t pid = fork();
  if (pid > 0)
  {
    int fp1 = open("pipe3", O_WRONLY);
    if (fp1 < 0)
    {
      perror("error");
      return -1;
    }

    while (1)
    {
      fgets(buff, sizeof(buff), stdin);
      ssize_t size = write(fp1, buff, strlen(buff));
      printf("write size = %ld\n", size);
      if (0 == strcmp(buff, ".quit\n"))
      {
        break;
      }
    }
    close(fp1);
    wait(NULL);
  }
  else if (0 == pid)
  {
    int fp2 = open("pipe4", O_RDONLY);
    if (fp2 < 0)
    {
      perror("error");
      return -1;
    }
    while (1)
    {
      memset(buff, 0, sizeof(buff));
      ssize_t size = read(fp2, buff, sizeof(buff));
      printf("size = %ld,buff = ---%s---\n", size, buff);
      if (0 == strcmp(buff, ".quit\n"))
      {
        break;
      }
      printf("d->c: %s\n", buff);
    }
    close(fp2);
  }
  else
  {
    perror("fork error");
  }
  return 0;
}
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "head.h"

int main(int argc, const char *argv[])
{
  int ret1 = mkfifo("pipe3", 0664);
  int ret2 = mkfifo("pipe4", 0664);
  if (ret1 < 0 && ret2 < 0 && errno != EEXIST)
  {
    perror("mkfifo error");
    return -1;
  }

  char buff[1024] = {0};

  pid_t pid = fork();
  if (pid > 0)
  {
    int fp2 = open("pipe4", O_WRONLY);
    if (fp2 < 0)
    {
      perror("error");
      return -1;
    }

    while (1)
    {
      fgets(buff, sizeof(buff), stdin);
      ssize_t size = write(fp2, buff, strlen(buff));
      printf("write size = %ld\n", size);
      if (0 == strcmp(buff, ".quit\n"))
      {
        break;
      }
    }
    close(fp2);
    wait(NULL);
  }
  else if (0 == pid)
  {
    int fp1 = open("pipe3", O_RDONLY);
    if (fp1 < 0)
    {
      perror("error");
      return -1;
    }
    while (1)
    {
      memset(buff, 0, sizeof(buff));
      ssize_t size = read(fp1, buff, sizeof(buff));
      printf("size = %ld,buff = ---%s---\n", size, buff);
      if (0 == strcmp(buff, ".quit\n"))
      {
        break;
      }
      printf("c->d: %s\n", buff);
    }
    close(fp1);
  }
  else
  {
    perror("fork error");
  }
  return 0;
}

信号

信号:进程间的通知机制(异步通信)

信号:软中断。CPU正在执行的任务可以被一个信号打断,中断后执行新的任务,新的任务结束继续执行之前的任务。

信号的操作:

  1. 发送信号 : kill、kill()

  2. 注册信号:signal()

  3. 信号的处理方式

    忽略:不处理

    缺省:按照操作系统默认方式处理

    捕获:按照自定义方式处理

#include "head.h"
int cnt = 1;
void handler(int signum)
{
  printf("chaoshi%d\n", cnt);
  if (3 == cnt)
  {
    exit(0);
  }
  cnt++;
  alarm(3);
}
int main(int argc, const char *argv[])
{
  char buff[512] = {0};
  signal(SIGALRM, handler);
  while (1)
  {
    alarm(3);
    fgets(buff, sizeof(buff), stdin);
    cnt = 1;
  }
}

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐