Linux

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > Linux > 什么是管道通信?Linux下匿名管道和命名管道

什么是管道通信?Linux下匿名管道和命名管道的区别与用法

作者:qualitymanmd

这篇文章主要介绍了什么是管道通信?Linux下匿名管道和命名管道的区别与用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

介绍

进程间通信目的

首先我们要了解进程间通信的目的,一共有4点

1:数据传输:一个进程需要将它的数据传输给另一个进程

2:资源共享:多个进程之间共享同样的资源

2:通知事件:一个进程给另一个进程发送信息,通知发生了某种事件

4:进程控制:某些进程希望完全控制另一个进程的执行,此时进程希望另一个进程能进行拦截另一个进程的一场,并能够及时知道它的状态改变

进程间通信发展

管道,SystemV进程间通信,POSIX进程间通信

其中这三个都有各自的分支

管道

什么是管道:管道是UNIX系统最古老的进程间通信方式

一个进程链接另一个进程的另一个数据流成为一个管道

匿名管道

这里是示例代码

#include<unistd.h>
//功能是创建无名管道
int pipe(int fd[2]);
//参数解释:fd为文件描述符数组,fd[0]是读端,fd[1]为写端

用fork来共享管道原理

站在文件描述符角度-深度理解管道

站在内核角度

测试管道读写代码示例

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#define ERR_EXIT(m)
do {
	perror(m);
	exit(EXIT_FAILURE);
} while (0)

int main(int argc, char* argv[])
{
	int pipefd[2];
	if (pipe(pipefd) == -1)
		ERR_EXIT("pipe error");
	pid_t pid;
	pid = fork();
	if (pid == -1)
	{
		ERR_EXIT("fork error");
	}
	if (pid == 0)
	{
		close(pipefd[0]);
		write(pipefd[1], "hello", 9);
		close(pipefd[1]);
		exit(EXIT_SUCCESS);
	}
	close(pipefd[1]);
	char buf[10] = { 0 };
	read(pipefd[0], buf, 10);
	printf("buf=%s\n", buf);
	return 0;
}

管道读写规则

当没有数据可读时

当管道满的时候

管道特点

只能用于具有共同祖先的进程之间进行通信,通常一个管道由一个进程创建,然后进程调用fork,此后父子进程之间可用该管道

管道提供流式服务

3-8验证管道通信的4种情况

命名管道

管道应用的一个限制就是只能在具有共同祖先的进程间通信

如果我们在不相关的进程间进行通信,可以用FIFO文件进行此工作,它通常被命名为管道

命名管道是一种特殊类型文件

创建命名管道

$ mkfifo filename

匿名管道和命名管道的区别

命名管道的打开规则

打开操作/未读/打开fifo

如果当前打开操作是为写⽽打开FIFO时

System V 共享内存

共享内存是最快的IPC形式,一旦这样的内存映射搭配共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不在通过执行进入内核的操作系统调用来传递彼此的数据

5-3 共享内存相关函数

一、shmget ():创建 / 获取共享内存

功能

创建一块新共享内存段,或获取已存在的共享内存段标识。

函数原型

int shmget(key_t key, size_t size, int shmflg);

参数说明

返回值

二、shmat ():挂载共享内存到进程虚拟地址空间

功能

将指定共享内存段映射、连接到当前进程的地址空间,挂载后进程可直接读写这块内存。

函数原型

void *shmat(int shmid, const void *shmaddr, int shmflg);

参数说明

地址对齐规则说明

实际挂载地址 = shmaddr - (shmaddr % SHMLBA)

返回值

三、shmdt ():卸载共享内存(脱离映射)

功能

断开当前进程与共享内存段的地址映射,进程无法再访问该共享内存。

注意:仅脱离进程映射,不会删除操作系统中的共享内存实体。

函数原型

int shmdt(const void *shmaddr);

参数说明

shmaddr:shmat 成功返回的共享内存首地址指针。

返回值

四、shmctl ():共享内存控制(删除 / 修改属性 / 获取状态)

功能

对共享内存执行控制操作:获取状态、修改权限、销毁共享内存段。

函数原型

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数说明

返回值

system V 消息队列

消息队列提供一个从一个进程向另外一个进程发送一块数据的方法

每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不用的类型值

特性方面

IPC资源必须删除,否则不会自动删除,除非自启,所以System V ipc资源的生命周期随内核变化而变化

system V 信号量

多个执行流程,能看到的同一份访问资源,共享资源

被保护起来的共享资源:临界资源

保护的方式常见为互斥和同步

任何时刻只允许一个执行流访问资源,叫做互斥

多个执行流,访问临界资源的时候,具有一定顺序性,叫做同步

系统中某些资源一次只允许一个进程实用,这样的称谓临界资源或互斥资源

在进程中涉及到互斥资源的程序段叫临界区。你写的代码=访问临界资源的代码(临界区)+不访问

临界资源的代码(⾮临界区)

•所谓的对共享资源进⾏保护,本质是对访问共享资源的代码进⾏保护

信号量

ipc资源必须删除,否则不会自动清除,除非重启,所以system v ipc 资源的生命周期随内核变化而变化

信号量是一个计数器

操作⽅⾯

内核是怎么组织管理IPC资源的

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文