IPC-管道

进程间通信概述

进程间通信(IPC: Inter Processes Communication)

  进程是一个独立的资源分配单元,不同进程(这 里所说的进程通常指的是用户进程)之间的资源是独 立的,没有关联,不能在一个进程中直接访问另一个 进程的资源(例如打开的文件描述符)。
  进程不是孤立的,不同的进程需要进行信息的交 互和状态的传递等,因此需要进程间通信。

进程间通信功能
  • 数据传输:一个进程需要将它的数据发送给另一个 进程。
  • 资源共享:多个进程之间共享同样的资源。 
  • 通知事件:一个进程需要向另一个或一组进程发送 消息,通知它们发生了某种事件。
  • 进程控制:有些进程希望完全控制另一个进程的执 行(如Debug进程),此时控制进程希望能够拦截
    另一个进程的所有操作,并能够及时知道它的状态 改变。

linux进程间通信(IPC)由以下几个部分发展而来:

  1. 最初的UNIX进程间通信
  2. SYSTEM V进程间通信
  3. POSIX进程间通信(POSIX:Portable Operating System interface可移植操作系统接口)
  4. Socket进程间通信

一、管道(pipe)

管道(pipe)又称无名管道。无名管道是一种特殊类型的文件,在应用层体现为两 个打开的文件描述符。
        在这里插入图片描述
管道是最古老的UNIX IPC方式,其特点是:

  • 半双工,数据在同一时刻只能在一个方向上流动。 
  • 管道不是普通的文件,不属于某个文件系统,其只存在于内存中。
  • 管道没有名字,只能在具有公共祖先的进程之间使用。-
  • 管道的缓冲区是有限的。管道是一个固定大小的缓 冲区。在Linux中,该缓冲区的大小为4Kbyte。
  • 管道所传送的数据是无格式的,这要求管道的读出方 与写入方必须事先约定好数据的格式,如多少字节算 一个消息等。
  • 数据只能从管道的一端写入,从另一端读出。从管道读数据是一次性操作,数据一旦被读走,它就从管道中被抛弃,释放空间以便写更多的数据。

管道由linux系统提供的pipe()函数创建,该函数的原型为:

#include <unistd.h>  
int pipe(int filedes[2]);

功能:经由参数filedes返回两个文件描述符
参数:filedes为int型数组的首地址,其存放了管道的 文件描述符fd[0]、fd[1]
   filedes[0]为读而打开,filedes[1]为写而打开 管道,filedes[0]的输出是filedes[1]的输入。
返回值:
    成功:返回 0
    失败:返回-1

父子进程通过管道实现数据的传输:
        在这里插入图片描述

二、命名管道(FIFO)

命名管道(FIFO)和管道(pipe)基本相同,但也有一些 显著的不同,其特点是:

  • FIFO在文件系统中作为一个特殊的文件而存在。 
  • 虽然FIFO文件存在于文件系统中,但FIFO中的内容 却存放在内存中,在Linux中,该缓冲区的大小为 4Kbyte。
  • FIFO有名字,不同的进程可以通过该命名管道进行 通信。
  • FIFO所传送的数据是无格式的。
  • 从FIFO读数据是一次性操作,数据一旦被读,它就从 FIFO中被抛弃,释放空间以便写更多的数据。
  • 当共享FIFO的进程执行完所有的I/O操作以后,FIFO将 继续保存在文件系统中以便以后使用。

在程序中调用 mkfifo() 函数创建一个命名管道文件,该函数的原型为:

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo( const char *pathname, mode_t mode);

参数: 
   pathname:FIFO的路径名+文件名。 
   mode:mode_t类型的权限描述符。
返回值: 
   成功:返回 0 
   失败:如果文件已经存在,则会出错且返回-1。
FIFO文件的读写 
因为使用pipe的进程通过继承获得了pipe的文件描 述符,所以pipe仅需要创建而不需要打开。
但是FIFO则需要打开,因为使用它们的进程可以没有任何关系。
一般文件的I/O函数都可以作用于FIFO,如open、 close、read、write等。

例子:
fifo_write.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
  int fd;
  int ret;
  char send[100] = "Hello I love you";
 
  ret = mkfifo("my_fifo", S_IRUSR|S_IWUSR);
  if(ret != 0)
  {
      perror("mkfifo");
  }
  printf("before open\n");
  fd = open("my_fifo", O_WRONLY);
  if(fd<0)
  {
      perror("open fifo");
  }
  printf("after open and before read\n");
  write(fd, send, strlen(send));
  printf("write to my_fifo buf=%s\n",send);
  return 0;
}

fifo_read.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
  int fd;
  int ret;
  char recv[100];
  ret = mkfifo("my_fifo", S_IRUSR|S_IWUSR);
  if(ret != 0)
  {
      perror("mkfifo");
  }
  printf("before open\n");
  fd = open("my_fifo", O_RDONLY);
  if(fd<0)
  {
      perror("open fifo");
  }
  printf("after open and before read\n");
  bzero(recv, sizeof(recv));
  read(fd, recv, sizeof(recv));
  printf("read from my_fifo buf=[%s]\n",recv);
  return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值