Linux IPC:命名管道的使用

  命名管道可以用于没有亲缘关系的进程间通信,本文简单介绍一下命名管道的具体使用。

一、命名管道的操作函数

int mkfifo(const *pathname,mode_t mode)

 作用:创建一个命名管道标识符

  • pathname:管道的标识符文件名称
  • mode:权限

 返回值:成功返回0,失败返回-1。如果返回EEXIST则表示管道的标识符文件已经存在了不需要重新创建。

 注意:此函数只是创建了一个命名管道的标识符,接下来对于命名管道的操作就和普通文件的操作很类似。

管道的特性:

  • 如果管道文件被只读打开,会阻塞,直到管道文件也被写方式打开
  • 如果管道文件被只写打开,会阻塞,直到管道文件也被读方式打开

二、命名管道的具体使用

  因为命名管道可以实现没有亲缘关系的进程间通信,因此我们写了两个程序,一个负责写,一个负责读。写进程给命名管道中发送数据,读进程通过同样的文件标识符从同一个命名管道中读取数据并打印。

写进程:
  创建名为test.fifo的命名管道标识符,然后打开管道标识符文件,得到命名管道的操作句柄,从而不断向命名管道写入数据。

读进程:
  创建名为test.fifo的命名管道标识符,如果已经存在就直接使用。通过打开管道标识符文件,得到命名管道的操作句柄,从而不断从命名管道读取数据并打印。

写进程如下:

#include<stdio.h>
#include<errno.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
//写进程
int main(){
    
    
  int ret = mkfifo("./test.fifo",0664);//创建命名管道的标识符
  if(ret<0 && errno != EEXIST){
    
    
    printf("标识符创建失败\n");
    return -1;
  }else{
    
    
    printf("标识符创建成功\n");
  }

  int fd = open("./test.fifo",O_WRONLY);//不能加创建选项,因为创建选项创建的是普通文件,而我们使用的是管道文件
  if(fd < 0){
    
    
    printf("文件打开失败\n");
    return -1;
  }else{
    
    
    printf("文件打开成功\n");
  }

  int num=1;
  while(1){
    
    
    char buf[1024]={
    
    0};
    sprintf(buf,"这是第%d次写入数据",num);//将数据打印到buf中
    int w_ret = write(fd,buf,strlen(buf));//向命名管道写入数据
    if(w_ret < 0){
    
    
      printf("文件写入失败\n");
      close(fd);
    }else{
    
    
      printf("第%d次写入成功\n",num);
    }
    num++;//更新次数
    sleep(1);
  }

  close(fd);//退出前关闭文件
}

读进程如下:

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

int main(){
    
    
  int ret = mkfifo("./test.fifo",0664);//创建命名管道标识符
  if(ret<0 && errno != EEXIST){
    
    
    printf("标识符创建失败\n");
    return -1;
  }else{
    
    
    printf("标识符创建成功\n");
  }

  int fd = open("./test.fifo",O_RDONLY);//以只读方式打开文件
  if(fd<0){
    
    
    printf("文件打开失败\n");
    return -1;
  }else{
    
    
    printf("文件打开成功\n");
  }

  while(1){
    
    
    char buf[1024]={
    
    0};//接收读取到的数据
    int r_ret = read(fd,buf,1023);//从命名管道读取数据
    buf[1023]='\0'; 
    if(r_ret<0){
    
    
      printf("数据读取失败\n");
      close(fd);
      return -1;
    }else if(r_ret == 0){
    
    
      printf("所有写端被关闭\n");
      close(fd);//所有写端被关闭,关闭文件,退出程序
      return -1;
    }else{
    
    
      printf("数据接收成功:%s\n",buf);
    }
  }
}

猜你喜欢

转载自blog.csdn.net/weixin_57761086/article/details/128528980