长生栈 长生栈
首页
  • 编程语言

    • C语言
    • C++
    • Java
    • Python
  • 数据结构和算法

    • 全排列算法实现
    • 动态规划算法
  • CMake
  • gitlab 安装和配置
  • docker快速搭建wordpress
  • electron+react开发和部署
  • Electron-创建你的应用程序
  • ImgUI编译环境
  • 搭建图集网站
  • 使用PlantUml画时序图
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Living Team

编程技术分享
首页
  • 编程语言

    • C语言
    • C++
    • Java
    • Python
  • 数据结构和算法

    • 全排列算法实现
    • 动态规划算法
  • CMake
  • gitlab 安装和配置
  • docker快速搭建wordpress
  • electron+react开发和部署
  • Electron-创建你的应用程序
  • ImgUI编译环境
  • 搭建图集网站
  • 使用PlantUml画时序图
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 文件操作

  • Linux进程和线程

  • Linux信号

  • 进程间通信

    • 无名管道
      • IPC机制
      • 管道
      • 无名管道
        • 创建无名管道
        • 无名管道创建示例代码
        • 读写管道
        • 读写管道示例代码
        • 输出
    • 有名管道
    • 信号量
    • 共享内存
    • 消息队列
  • Socket

  • C语言
  • 进程间通信
DC Wang
2023-02-20
目录

无名管道

# 无名管道

Linux 提供了多种进程间通信(IPC)方式,其中之一就是管道。管道又可分为两种:无名管道(pipe)和有名管道(fifo)。在终端上,使用无名管道可以像这样:ls ./ | less。

# IPC机制

  • Linux有多种进程间通信(IPC)方式,如果没有IPC,进程只能通过文件系统互相交换信息。

  • 常用的IPC有如下几种:

    • 管道
    • 信号量
    • 共享内存
    • 消息队列

# 管道

管道分为两种:

  • 无名管道(pipe):是与内存中的一个索引节点相关联的两个文件描述符,没有名字,不会在文件系统中出现。

    例子:下面命令使用 |作为无名管道,将ls的输出传给less命令的输入。

    $ ls ./ | less
    
    1
  • 有名管道(fifo):出现于文件系统当中,遵循先入先出的原则来读取数据。

    例子:下面命令使用mkfifo fifo,创建一个有名管道名为fifo,ls的输出传到fifo中,less从fifo中取内容。

    当终端2先执行less < ./fifo时,没有内容输出,终端1执行ls ./ > fifo后,终端2开始输出。

    $ mkfifo fifo
    
    # 终端1
    $ ls ./ > fifo
    
    # 终端2
    $ less < ./fifo
    
    1
    2
    3
    4
    5
    6
    7

pipe、fifo的名称并非硬性规定。

# 无名管道

  • 管道是半双工,数据只能单向传递

  • 管道只能在相关的、有共同祖先的进程之间使用

# 创建无名管道

创建管道使用pipe调用,关闭管道使用close调用

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

如果成功建立了管道,则会打开两个文件描述符并把它们的值保存在一个整数数组中。其中,filedes[0]用于读出数据,filedes[1]用来写入数据 。成功返回0,否则返回-1。

# 无名管道创建示例代码

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

int main(void)
{
	int fd[2]; /* Array for file descriptors */

	if((pipe(fd)) < 0) {
		perror("pipe");
		exit(EXIT_FAILURE);
	}
	printf("descriptors are %d, %d\n", fd[0], fd[1]);
	close(fd[0]);
	close(fd[1]);
	exit(EXIT_SUCCESS);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 读写管道

从管道读出数据和写入数据,只要简单的使用read和write调用即可。read从fd[0]中读取数据,write向fd[1]中写入数据。

  • 如果父进程向子进程发送数据,则父进程需关闭fd[0]并向fd[1]写入数据,子进程需关闭fd[1],并从fd[0]读取数据。
  • 反之亦然

# 读写管道示例代码

cat功能的又一实现

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>

#define BUFSZ PIPE_BUF

void err_quit(char *msg);

int main(int argc, char *argv[])
{
	int fd[2]; /* File descriptor array for the pipe */
	int fdin; /* Descriptor for input file */
	char buf[BUFSZ];
	int pid, len;

	/* Create the pipe */
	if((pipe(fd)) < 0)
		err_quit("pipe");
	
	/* Fork and close the appropriate descriptors */
	if((pid = fork()) < 0)
		err_quit("fork");
	if (pid == 0) {
	/* Child is reader, close the write descriptor */
		close(fd[1]);
		while((len = read(fd[0], buf, BUFSZ)) > 0)
			write(STDOUT_FILENO, buf, len);
		close(fd[0]);
	} else {
		/* Parent is writer, close the read descriptor */
		close(fd[0]);
		if((fdin = open(argv[1], O_RDONLY)) < 0) {
			perror("open");
			/* Send something */
			write(fd[1], "123\n", 4);
		}
		else {
		while((len = read(fdin, buf, BUFSZ)) > 0)
			write(fd[1], buf, len);
		close(fdin);
	}
	/* Close the write descriptor */
	close(fd[1]);
	}
	/* Reap the exit status */
	waitpid(pid, NULL, 0);

	exit(EXIT_SUCCESS);
}
	
void err_quit(char *msg)
{
	perror(msg);
	exit(EXIT_FAILURE);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

# 输出

$ ./piperw abc.txt
adcdef
1
2
编辑 (opens new window)
#Linux#进程间通信#IPC
上次更新: 2023/03/31, 22:34:04
信号集处理
有名管道

← 信号集处理 有名管道→

最近更新
01
ESP32-网络摄像头方案
06-14
02
ESP32-PWM驱动SG90舵机
06-14
03
ESP32-实时操作系统freertos
06-14
更多文章>
Theme by Vdoing | Copyright © 2019-2025 DC Wang All right reserved | 辽公网安备 21021102001125号 | 吉ICP备20001966号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式