前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >进程间通讯(二).fifo(1)

进程间通讯(二).fifo(1)

作者头像
franket
发布2021-09-16 09:41:51
5510
发布2021-09-16 09:41:51
举报
文章被收录于专栏:技术杂记技术杂记

前言

UNIX/Linux 是多任务的操作系统,通过多个进程分别处理不同事务来实现,如果多个进程要进行协同工作或者争用同一个资源时,互相之间的通讯就很有必要了

进程间通信,Inter process communication,简称 IPC,在 UNIX/Linux 下主要有以下几种方式:

  • 无名管道 ( pipe )
  • 有名管道 ( fifo )
  • 信号 ( signal )
  • 信号量 ( semaphore )
  • 消息队列 ( message queues )
  • 共享内存 ( shared memory )
  • 套接字 ( socket )

这里分享一下我在学习进程通讯过程中的笔记和心得


概要


FIFO

FIFO 有时被称为命名管道

匿名管道 pipe 只能在两个相关的进程之间使用,而且这两个相关的进程还要有一个共同的创建它们的祖先进程,而通过 FIFO 不相关的进程也能交换数据

sys/stat.h 中有关于 mkfifo 的原型声明

代码语言:javascript
复制
/* Create a new FIFO named PATH, with permission bits MODE.  */
extern int mkfifo (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

下面通过一个例子,演示一下 FIFO 的使用方法


代码示例

要求

有A、B两个进程(非亲缘),实现如下功能:

  • 1.A进程将字符串如“12345”发送给B进程
  • 2.B进程收到后显示为“54321”,并将首尾两个字符去掉后,反传给A进程
  • 3.A进程收到后显示为“432”

要求:用fifo做

提示:要用2个fifo

代码示例

fifoB.c

代码语言:javascript
复制
#include <unistd.h> //access,read,write,close 都在这里声明
#include <sys/stat.h> //mkfifo 在这里声明
#include <errno.h> //EEXIST 和 errno 在这里定义
#include <stdio.h>
#include <stdlib.h> //exit 在这里声明
#include <fcntl.h> //O_RDONLY 和 O_WRONLY 还有open在这里定义和声明

#define MAXSIZE 1000

//process B

int slen(char *s) //定义一个计算字符串长度的函数
{
  int i=0;
  for(;*s!='\0';s++)i++;
  return i;
}

char * srev(char *s) //这个函数用来翻转字符串
{
  int i=0,len=slen(s);
  char tmpc='\0';
  for(i=0;i<len/2;i++)
  {
    tmpc=s[i];
    s[i]=s[len-1-i];
    s[len-1-i]=tmpc;
  }
  return s;
}

int main() 
{
  char * rfifo="/tmp/abfifo"; 
  char * wfifo="/tmp/bafifo";
  char buffer[MAXSIZE],tmpc='\0';
  int i=0,rfd=0,wfd=0,res=-1,len=0,rres=0; //在定义变量的同时进行初始化,是一个好习惯
  
  
  // mkfifo abfifo
  if(-1 == access(rfifo,F_OK)) //如果rfifo不存在,则创建
  {
    if(0 > (mkfifo(rfifo,0600)) && (EEXIST != errno)) //如果创建rfifo失败,并且出错不是文件已经存在,则提示并返回
    {
      printf("cannot create fifo file %s\n",rfifo);
      exit(res);
    }
  }

  // mkfifo bafifo
  if(-1 == access(wfifo,F_OK)) //如果wfifo不存在,则创建
  {
    if(0 > (mkfifo(wfifo,0600)) && (EEXIST != errno))  //如果创建wfifo失败,并且出错不是文件已经存在,则提示并返回
    {
      printf("cannot create fifo file %s\n",wfifo);
      exit(res);
    }
  }
  if(-1 == (rfd = open(rfifo,O_RDONLY))) //打开rfifo
  {
    printf("cannot open file:%s\n",rfifo);
    return res;
  }

  if(-1 == (wfd = open(wfifo,O_WRONLY))) //打开wfifo
  {
    printf("cannot open file:%s\n",wfifo);
    return res;
  }
  
  for (i=0;1 == (rres=read(rfd,&tmpc,sizeof(char)));i++) //从rfifo中遍历所有内容,都临时存放到tmpc中(一次一个字节)
  {
    buffer[i]=tmpc; //将tmpc存放到buffer中
    printf("%c",tmpc);  //将tmpc进行打印
    if ('\0' == tmpc) break; //如果遇到字符串结尾,就跳出
  }

  if(-1 == rres) //如果read的返回值为-1,就代表读错误
  {
    printf("read error on %s\n",rfifo);
    return res;
  }
  printf("\n");
  srev(buffer); //将buffer内容翻转
  printf("%s\n",buffer); //将翻转后的buffer输出
  
  len=slen(buffer); //求buffer的长度
  if( -1 ==(write(wfd,&buffer[1],sizeof(char)*(len-2)))) //将首尾去除后中间的部分写到wfifo中
  {
    printf("write error on : %s\n",wfifo);
    return res;
  }
    
  close(rfd);
  close(wfd); //收尾的文件描述符关闭
  res=0;
  return res;
}

fifoA.c

代码语言:javascript
复制
#include <stdio.h>
#include <malloc.h>
#include <string.h> //strlen,strcpy,strcat
#include <fcntl.h> //open,O_WRONLY,O_RDONLY 
#include <stdlib.h> //exit
#include <unistd.h> //write,access,read,close

//process A

int main(int argc,char *argv[])
{
  char * rfifo="/tmp/bafifo"; 
  char * wfifo="/tmp/abfifo";
  char tmpc='\0', * buffer=NULL;
  int len=0,rfd=0,wfd=0,res=-1,i=0,rres=0; //在定义变量的同时进行初始化,是一个好习惯

  if(2 != argc) //如果参数个数不达标,就提示并返回
  {
    printf("argument unmber error: need a string\n");
    return res;
  }
  len=strlen(argv[1]);
  buffer=(char *)malloc(sizeof(char)*(len+1)); //分配动态内存
  if (-1==(wfd=open(wfifo,O_WRONLY))) //打开wfifo
  {
    printf("open fifo file error:%s\n",wfifo);
    exit(res);
  }
  
  strcpy(buffer,argv[1]); //将参数复制给buffer
  strcat(buffer,""); //buffer构成字符串

  if (-1==write(wfd,buffer,sizeof(char)*(len+1))) //将buffer内容写到wfifo中
  {
    printf("write error on : %s\n",wfifo);
    exit(res);
  }
  
  if(-1 == access(rfifo,F_OK)) //检测rfifo是否已经存在
  {
    printf("cannot access fifo file %s\n",rfifo);
    return res;
  }

  if(-1 == (rfd = open(rfifo,O_RDONLY))) //打开rfifo
  {
    printf("cannot open pipe file:%s\n",rfifo);
    return res;
  }

  for (i=0;1 == (rres=read(rfd,&tmpc,sizeof(char)));i++) //从rfifo中遍历所有内容,并且逐个存到tmpc中
  {
    buffer[i]=tmpc; //将tmpc 存到 buffer中
    printf("%c",tmpc); //将tmpc输出
    if ('\0' == tmpc) break; //遇到字符串结束符就跳出
  }
  if(-1 == rres) //如果读的返回结果为-1就表明读错误
  {
    printf("read error on %s\n",rfifo);
    return res;
  }
  printf("\n");

  close(wfd);
  close(rfd); 
  free(buffer); //进行收场的清理工作
  res=0;
  return res;
}

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 概要
    • FIFO
      • 代码示例
        • 要求
        • 代码示例
    相关产品与服务
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档