设为首页 加入收藏

TOP

Linux进程通信 | 管道与FIFO(一)
2023-07-23 13:38:12 】 浏览:44
Tags:Linux 程通信 管道与 FIFO

Linux进程间通信通常使用的方式有很多种,其中比较常用的包括管道(pipe)和 FIFO(命名管道)。本文将介绍这两种通信方式的基本概念,并用C语言编写示例代码,来说明如何在两个进程之间使用这些IPC机制进行通信。

管道(pipe)

管道是一种半双工的通信方式,用于父进程和子进程之间的通信。在 Linux 中,管道是一种特殊的文件,有两个端点,一个读端和一个写端。管道的基本操作包括创建管道、关闭文件描述符、读取数据和写入数据等。

创建管道

在 Linux 中,我们可以使用 pipe() 系统调用来创建管道。pipe() 函数的原型如下:

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

其中,pipefd 是一个数组,用于存储管道的读端和写端的文件描述符。pipe() 函数成功时返回 0,失败时返回 -1。

下面是一个创建管道的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    int pipefd[2];
    
    // 创建管道
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    
    printf("读端文件描述符:%d\n", pipefd[0]);
    printf("写端文件描述符:%d\n", pipefd[1]);
    
    exit(EXIT_SUCCESS);
}

  • 编译并运行,打印如下
读端文件描述符:3
写端文件描述符:4

管道的读写

在使用管道进行通信时,父进程和子进程可以通过管道进行数据的读取和写入。在 C 语言中,我们可以使用 read()函数和 write() 函数来读取和写入数据。read() 函数用于从管道中读取数据,write() 函数用于向管道中写入数据,使用 close() 函数关闭文件描述符。在管道的使用中,我们应该在不需要的时候关闭管道的读端和写端,以避免资源浪费。

这三个函数的原型分别如下:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);

下面是一个父进程向子进程写入数据并读取返回结果的示例代码:

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

#define BUF_SIZE 1024

int main()
{
    int pipefd[2];
    pid_t pid;
    char buf[BUF_SIZE];
    int status;
    
    // 创建管道
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    
    // 创建子进程
    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    
    if (pid == 0) { // 子进程        
        // 从管道中读取数据
        if (read(pipefd[0], buf, BUF_SIZE) == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }
        
        printf("子进程收到消息:%s\n", buf);
        
        // 发送消息给父进程
        const char* message = "Hello, parent!";
        if (write(pipefd[1], message, strlen(message) + 1) == -1) {
            perror("write");
            exit(EXIT_FAILURE);
        }
        close(pipefd[1]); // 关闭写端
        exit(EXIT_SUCCESS);
    } else { // 父进程 
        // 发送消息给子进程
        const char* message = "Hello, child!";
        if (write(pipefd[1], message, strlen(message) + 1) == -1) {
            perror("write");
            exit(EXIT_FAILURE);
        }
        
        // 等待子进程退出
        wait(&status);
        if (WIFEXITED(status)) {
            printf("子进程退出,返回值:%d\n", WEXITSTATUS(status));
        }
        
        // 从管道中读取数据
        if (read(pipefd[0], buf, BUF_SIZE) == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }
        printf("父进程收到消息:%s\n", buf);
        close(pipefd[0]); // 关闭读端
        
        exit(EXIT_SUCCESS);
    }
}

在这个示例代码中,父进程先向子进程发送一条消息,子进程收到消息后向父进程发送一条消息,并退出。父进程在等待子进程退出后再从管道中读取子进程发送的消息。

  • 编译并运行,打印如下
子进程收到消息:Hello, child!
子进程退出,返回值:0
父进程收到消息:Hello, parent!

FIFO(命名管道)

FIFO(命名管道)是一种文件系统对象,与管道类似,也可以用于进程间通信。FIFO 是一种特殊类型的文件,它可以在文件系统中被创建,并且进程可以通过文件描述符来读取和写入数据。

与管道不同的是,FIFO 可以被多个进程打开,并且可以在文件系统中以路径的形式存在,因此不像管道那样只能在具有亲缘关系的进程之间使用。任何进程只要有相应的权限就可以打开 FIFO 并进行通信。

FIFO 的创建和使用

FIFO 的创建和使用也比较简单。首先需要使用 mkfifo() 函数创建 FIFO 文件,其原型如下

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

其中,pathname 是 FIFO 文件的路径名,mode 是文件的权限。

创建 FIFO 文件后,就可以像使用普通文件一样打开它,并使用 read() 和 write() 函数进行数据的读写。

下面是一个使用 FIFO 进行进程间通信的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇linux自定义man搜索路径 下一篇Linux进程通信 | 共享内存

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目