Linux进程间通信---管道

1、管道通信

管道通信类似于水流在水管中流动,只能一个方向传输数据。分为无名管道和命名管道(FIFO)。

1.1 无名管道

特点:

  • 半双工(数据只能一个方向进行流动)
  • 主要应用于父子进程或者兄弟进程
  • 不会以文件的形式存在于磁盘之中(存在于内存之中,父子进程结束后,便会消失)
  • 管道数据读取之后就没了
  • 创建的管道位于内核之中

用到的API函数:

#include <unistd.h>
int pipe(int pipefd[2]); //创建管道,成功返回0;失败返回-1

描述:

  1. 创建管道需要用到pipe()函数,pipe()函数需要一个有两个元素的数组(pipefd[.2]),返回值是一个整型数。其中pipefd[.2]表示两个文件描述符,pipefd[0]只为读打开,pipefd[1.]只为写打开
  2. 在写时,应先把读关闭(close(pipefd[0]) ),反之,在读时应先把写关闭( close(pipefd[1.]))

*[注:数组里面的.只是为了显示完整才加的(第一次使用csdn,不会操作),具体写代码时没有]

具体示例代码:

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

int main()
{
	int fd[2];  //定义一个数组---后续的文件描述符
	int pid;    //定义一个整型,用来描述后续的进程id
	
	//调用pipe函数创建管道,并判断是否创建成功
	if(pipe(fd) == -1)  
	{
		printf("创建管道失败\n");
		exit(-1);
	}

	//创建子进程,进行父子进程间的通信
	pid = fork();                //pid接收进程的id
	if(pid > 0)                 //pid大于0,表示父进程
	{
		sleep(3);               //父进程睡3秒,让子进程先进行,当然此时子进程应该是堵塞状态
		printf("这是父进程\n");
	
		close(fd[0]);           //关闭读的文件描述符
		//向管道内写
		write(fd[1],"this is from father!", strlen("this is from father"));  
		wait();                 //等待子进程退出后,父进程再退出
	}
	else if(pid == 0)           //pid 等于0,表示子进程
	{
		printf("这是子进程\n"); 
	
		close(fd[1]);           //关闭写的文件描述符
		char buf[128] = {0};    //创建一个数组作为读取时的缓冲区

		read(fd[0], buf,128);   //将读取的数据放在buf 内
		printf("get from father: %s\n",buf);
		exit(0);                //子进程退出
	}
	else
	{
		printf("创建进程失败\n");
	}
	return 0;
}

*[注:管道函数pipe,读写时调用的是 read() write()函数]

1.2 命名管道(FIFO)

特点:

  • 可用于无关进程间的通信
  • 会以特殊设备文件形式存在磁盘之中

相关API函数

#include <sys/stat.h>
#include <sys/types.h>
int mkfifo(const char* pathname, mode_t mode); //创建管道,成功返回0,失败返回-1

描述:第一个参数 pathname 是管道名,第二个参数 mode 和 open() 函数的 mode 一样 ,意思应该是对管道文件的操作权限

open() 函数的 mode 选择: 0600 可读可写

具体示例代码:

①创建命名管道并判断文件是否存在

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

int main()
{
	int ret;
	//创建命名管道,“./file”表示在当前路径下建立文件file, 文件权限是0600
	ret = mkfifo("./file",0600); 
	if(ret == 0)                 //返回值是0,表示创建成功
	{
		printf("创建成功\n");
	}
	else if(ret == -1)           //返回值是-1,表示创建失败  失败原因有很多,可以man 3 mkfifo查看具体原因
	{
		printf("创建失败\n");
		perror("Why");       //调用perror()函数可以查看错误原因 
	}
	 
	return 0;
}

上述代码运行结果:第一次运行:创建成功
—————————第二次运行:创建失败 Why:File exists (表示文件已经存在)

优化上述代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
int main()
{
	//创建命名管道,“./file”表示在当前路径下建立文件file, 文件权限是0600 可读可写
	//errno表示错误类型
	if((mkfifo("./file",0600)) == -1 && errno != EEXIST) 
	{
		printf("创建文件失败\n");
		perror("Why");       //调用perror()函数可以查看错误原因 
	}
	else
	{
		if(errno == EEXIST)
		{
			printf("文件已存在\n");
		}
		else
		{
			printf("创建成功\n");
		}
	}
	 
	return 0;
}

其他函数: perror()函数----判断错误原因 errno检查错误类型

②实现不同进程间通信
读取信息

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

int main()
{
	//创建命名管道,“./file”表示在当前路径下建立文件file, 文件权限是0600 可读可写
	//errno表示错误类型
	if((mkfifo("./file",0600)) == -1 && errno != EEXIST) 
	{
		printf("创建文件失败\n");
		perror("Why");       //调用perror()函数可以查看错误原因 
	}
	 //以只读的方式打开管道文件file  此时默认堵塞,直到另一个进程以只写的方式打开file文件  
	 //如果想要不堵塞加  O_RDONLY|O_NONBLOCK	
	int fd = open("./file",O_RDONLY); 
	if(fd != -1)
	{
		printf("read open success\n");
	}
	
	char buf[128] = {0};     //开辟缓冲区
	int n_read = read(fd,buf,128); //从管道文件file中读取数据到buf中

	printf("read %d byte from write: %s\n",n_read,buf);
	
	close(fd);
	return 0;
}

写信息

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

int main()
{
	
	 //以只写的方式打开管道文件file  此时会堵塞,直到另一个进程以只读的方式打开file文件	
	int fd = open("./file",O_WRONLY); 
	if(fd != -1)
	{
		printf("write open success\n");
	}
	
	char* buf= "this is message from file";     //发送的数据内容
	write(fd,buf,strlen(buf));                  //写到管道文件file中
	
	close(fd);
	return 0;
}

以上是关于管道通信的相关理论以及代码示例
简单来说:
1、无名管道不能满足无关进程间的通信,但命名管道可以满足
2、无名管道不会以文件形式存在磁盘中,但命名管道会以特殊设备文件形式存在磁盘中
3、二者都是调用 read() write()函数进行读写操作!
4、二者的数据都是单一方向流动,并且读数据之后,管道内的数据就没了
这是本人学习笔记,如有侵权,请告之!

### 关于 UniApp 框架推荐资源与教程 #### 1. **Uniapp 官方文档** 官方文档是最权威的学习资料之一,涵盖了从基础概念到高级特性的全方位讲解。对于初学者来说,这是了解 UniApp 架构技术细节的最佳起点[^3]。 #### 2. **《Uniapp 从入门到精通:案例分析与最佳实践》** 该文章提供了系统的知识体系,帮助开发者掌握 Uniapp 的基础知识、实际应用以及开发过程中的最佳实践方法。它不仅适合新手快速上手,也能够为有经验的开发者提供深入的技术指导[^1]。 #### 3. **ThorUI-uniapp 开源项目教程** 这是一个专注于 UI 组件库设计实现的教学材料,基于 ThorUI 提供了一系列实用的功能模块。通过学习此开源项目的具体实现方式,可以更好地理解如何高效构建美观且一致的应用界面[^2]。 #### 4. **跨平台开发利器:UniApp 全面解析与实践指南** 这篇文章按照章节形式详细阐述了 UniApp 的各个方面,包括但不限于其工作原理、技术栈介绍、开发环境配置等内容,并附带丰富的实例演示来辅助说明理论知识点。 以下是几个重要的主题摘选: - **核心特性解析**:解释了跨端运行机制、底层架构组成及其主要功能特点。 - **开发实践指南**:给出了具体的页面编写样例代码,展示了不同设备间 API 调用的方法论。 - **性能优化建议**:针对启动时间缩短、图形绘制效率提升等方面提出了可行策略。 ```javascript // 示例代码片段展示条件编译语法 export default { methods: { showPlatform() { console.log(process.env.UNI_PLATFORM); // 输出当前平台名称 #ifdef APP-PLUS console.log('Running on App'); #endif #ifdef H5 console.log('Running on Web'); #endif } } } ``` #### 5. **其他补充资源** 除了上述提到的内容外,还有许多在线课程视频可供选择,比如 Bilibili 上的一些免费系列讲座;另外 GitHub GitCode 平台上也有不少优质的社区贡献作品值得借鉴研究。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值