进程通信——有名管道

上一篇文章中学习了进程间通信的一种简答的方法:匿名管道。但是它只能用于具有亲缘关系的进程之间的通信。而FIFO的通信机制与之相似,却可以在任意两个进程之间通信。

FIFO文件操作

创建FIFO类似于创建文件,确实,FIFO可以存在于文件系统中。下面是创建FIFO的函数:

#include <sys/stat.h>
int mkfifi(const char *pathname, mode_t mode);
                                返回值:若成功返回0,若出错返回-1

参数说明:

pathname: FIFO文件的路径
mode: 设置FIFO文件属性的模式字,通常设为0666
返回值:若成功返回0,若出错返回-1

下面是一个简答的利用mkfifo函数来创建FIFO文件的例子,并利用了ls命令来查看其属性:

int ret;
mode_t mode = 0666;
if ((ret = mkfifo("./fifo",  mode)) < 0)
{
    printf("mkfifo error the return code is %s\n", strerror(errno));
    return -1;
}

在创建好FIFO文件之后,需要调用 open 函数打开FIFO文件,然后在此基础上执行read write 等操作。下面是关于 FIFO 文件操作的一些注意点。

注意点:

  

  • 跟管道类似,如果对写进程不存在的FIFO执行read操作,总是返回0;这意味着如果写进程提前关闭FIFO文件,并且FIFO中不存在数据时,read操作将直接返回0,而不会阻塞。如果对进程不存在的FIFO执行write操作,出错返回-1,产生SIGPIPE信号。
  • 如果open时没有设置O_NONBLOCK,则以读方式打开FIFO文件,必须存在以写方式打开此FIFO文件的进程,否则一直阻塞;以写方式打开FIFO,如果不存在以读方式打开FIFO的进程,也会一直阻塞
  • 如果设置了 O_NONBLOCK,以读或写方式打开FIFO会立即返回。返回值会根据有没有相应的写或者读进程提出出错与否。

下面是一段测试代码:

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

int main()
{
    int ret;
    int fd;
    mode_t mode = 0666;
    if ((ret = mkfifo("./fifo",  mode)) < 0)
    {
        printf("mkfifo error the return code is %s\n", strerror(errno));
        return -1;
    }

    // 测试没有设置O_NONBLOCK标识且写进程不存在,这个操作会一直阻塞
    if ((fd = open("./fifo", O_RDONLY)) < 0)
        printf("open error the return code is %s\n", strerror(errno));

    // 测试没有设置O_NONBLOCK标识且读进程不存在,这个操作会一直阻塞
    if ((fd = open("./fifo", O_WRONLY)) < 0)
        printf("open error the return code is %s\n", strerror(errno));

    return 0;
}

实例

下面是一段利用FIFO实现服务器与客户端通信的例子:

/*
 * file : FIFOread.c
 *
 */

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

int main()
{
    int ret;
    int fd;
    mode_t mode = 0666;
    if ((ret = mkfifo("./fifo",  mode)) < 0)
    {
        printf("mkfifo error the return code is %s\n", strerror(errno));
        return -1;
    }

    // open the fifo file and papare to read
    if ((fd = open("./fifo", O_RDONLY)) < 0)
    {
        printf("open error the return code is %s\n", strerror(errno));
        return -1;
    }

    // read the data from client and print
    int nRead;
    char line[1024];
    while ((nRead = read(fd, line, 1024)) > 0)
    {
        printf("the recv bytes is %d\n", nRead);
        printf("the recv msg is %s\n", line);
    }

    printf("the return nRead is %d\n", nRead);
    close(fd);
    return 0;
}
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int main()
{
    int fd;
    // open test without O_NOBLOCK flag
    if ((fd = open("./fifo", O_WRONLY)) < 0)
    {
        printf("open error the return code is %s\n", strerror(errno));
        return -1;
    }

    int i;
    int nWrite;
    char line[100] = "Hello FIFO\n";

    for (i = 0; i < 10; i++)
    {
        if ((nWrite = write(fd, line, sizeof(line))) < 0)
        {
            printf("wirte error\n");
            return -1;
        }
        sleep(1);

    }

    close(fd);
    return 0;
}
时间: 2024-10-02 19:23:18

进程通信——有名管道的相关文章

Linux 进程通信之管道

管道是单向的.先进先出的,它把一个进程的输出和另一个进程的输入连接在一起.一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据.数据被一个进程读出后,将被从管道中删除,其他读进程将不能再读到这些数据.管道提供了简单的流控制机制,进程试图读空管道时,进程将阻塞.同样,管道已经满时,进程再试图向管道写入数据,进程将阻塞. 管道包括无名管道和有名管道两种,无名管道只能用于父进程和子进程间的通信,而有名管道可以用于同一系统中的任意两个进程间的通信. 无名管道由pipe()函数

进程通信-无名管道

无名管道:主要是针对进程通信的(自己感觉它有很大的局限性) 特点:它不是一个文件系统,不能按名访问,这也是它和有名管道之间最大的区别.无名管道只是一个系统内存里面的东西. 半双工模式,数据只能流向一个方向(老师给我们举得例子就是水厂的水到居民用水,不可能倒着流对吧). 进程之间通信,但是只能是有亲缘关系的进程才能进行通信?比如父子进程:因为在父子进程中,子进程拷贝父进程的数据段,这让这两个进程在通信的时候就有了相连的关系. 下面我们来看一下:无名管道的创建,写入,读取,关闭(我用的的是Liunx

linux进程通信之管道

1.介绍: 1)同一主机: unix进程通信方式:无名管道,有名管道,信号 system v方式:信号量,消息队列,共享内存 2)网络通信:Socket,RPC 2.管道: 无名管道(PIPE):使用一个进程的标准输出作为另一个进程的标准输入建立的一个单向管道,执行完成后消失.主要用于父进程与子进程之间,或者两个兄弟进程之间.采用的是单向 1)创建无名管道:(#include(unistd.h)) extern int pipe(int pipes[2]),pipes[0]完成读操作,pipes

Linux下进程通信之管道

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication).如下图所示. 目前进程通信的方式有: 管道 FIFO 消息队列 信号量 共享内存 套接字 管道 管道概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数

进程通信——匿名管道

有的时候在程序的开发过程中,两个进程之间会有数据的交互.信号的机制能够实现进程通信.它通过 “中断--响应” 的异步模式来工作.但作为通信来讲,信号还是远远不够的.因为它不能够携带任何其他的信息.只利用信号机制来实现进程通信显得捉襟见肘,并且信号的优势并不此.所以必须开发新的进程间通信的方法.本文所学习的 "匿名管道" 便是其中的一种最简单的方法. 基本概念 在讲管道的基本概念之前,首先提一个问题.如果让你来设计进程通信的方式,你会怎么做?最简单的方式莫过于两个进程打开同一个文件,这样

Linux学习笔记(13)-进程通信|命名管道

匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢? 别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道-- 所谓命名管道,那便是拥有名字的管道,同时也被称之为FIFO,谈到FIFO,那么做过单片机开发的同学想必是不陌生的. 在很多单片机的项目中,都使用过FIFO,FIFO其实是一种队列,先进先出,这样可以保证读出数据和写入数据的一致性. 使用FIFO文件,便可以在不同的,且不具有亲属关系的进程中进程通信. 创建命

进程通信之管道

本节学习进程通信的另一种方式:管道.管道是一个进程连接数据流到另一个进程的通道,它通常把一个进程的输出通过管道连接到另一个进程的输入.在shell命令中经常会看到管道的应用,比如我们要列出当前文件下所有命名中有"test"的文件:ls -l | grep test.其中"|"就代表我们在使用管道,它会把"ls -l"的查询结果通过管道,发送给grep,然后执行"grep test"命令后把结构输出到终端.总之一句话:管道会把一

Linux进程通信----匿名管道

Linux进程通信中最为简单的方式是匿名管道 匿名管道的创建需要用到pipe函数,pipe函数参数为一个数组 表示的文件描述字.这个数组有两个文件描述字,第一个是用 于读数据的文件描述符第二个是用于写数据的文件描述符. 不能将用于写的文件描述符进行读操作或者进行读的文件描述 符进写操作,这样都会导致错误. 关于匿名管道的几点说明: 1.匿名管道是半双工的,即一个进程只能读,一个进程只能写    要实现全双工,需要两个匿名管道. 2.只能在父子进程或者兄弟进程进行通信. 3.在读的时候关闭写文件描

进程通信之管道通信

编写两个程序,一个程序是对管道的写数据.另一个是对管道的读数据. 有名管道的创建mkfifo 读数据:fifo_read.c /* fifo_read.c */ #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <lim