ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

系统编程第二节——管道

2021-07-20 23:33:25  阅读:156  来源: 互联网

标签:int 编程 管道 fd 第二节 sizeof include buf


Linux进程间通信

1、进程间通信的类型

  1. 管道(pipe)和命名管道(FIFO)
  2. 信号(signal)
  3. 共享内存
  4. 消息队列
  5. 信号量
  6. 套接字

2、管道

  管道是Linux中最常用的进程间通信 IPC 机制。使用管道时,一个进程的输出可以成为另外一个进程的输入。
  当输入/输出的数据量特别大时,管道的这种 IPC 机制就非常有用。
  在Linux中,通过将两个file结构指向同一个临时的VFS节点,这个VFS节点又指向同一个物理页而实现管道。

3、pipe管道

若要创建一个简单的管道,可以使用系统调用pipe(),它接受一个参数,也就是一个包括两个整数的数组。如果系统调用成功,此数组将包括管道使用的两个文件描述符,一个为读端,一个为写端。pipe管道是半双工的,数据只能向一个方向流动,需要双方通信时,就建立两个管道。pipe管道只能用于父子进程或者兄弟进程之间。

头文件: #include <unistd.h>

函数原型: int pipe( int filedes[2])
filedes: 管道文件描述符,当为0时,pipe端代码工程为读端;当为1时,pipe端代码工程为写端;
filedes[0]: 管道的读端
filedes[1]: 管道的写端
函数返回值:成功为 0 ;错误为 1

#include <stdio.h>
#include <unistd.h>
#include <string.h>
/*父子进程通过无名管道进行通信*/
int main(int argc, char *argv[])
{
	//1, 创建无名管道
	int fd[2];
	char buf[64];	
	
	int ret = pipe(fd);
	if(-1 == ret)
	{
		perror("pipe failed");
		return -1;
	}
	
	//2, 创建子进程
	pid_t pid = fork();
	if(-1 == pid)
	{
		perror("fork faied");
		return -1;
	}
	//3, 父进程循环从键盘获取数据写入无名管道 --> 写入端 fd[1]
	if(pid > 0)
	{
		while(1)
		{
			memset(buf, 0, sizeof(buf));
			fgets(buf, sizeof(buf), stdin);	
			write(fd[1], buf, sizeof(buf));
		}
	}
	//4, 子进程循环从无名管道中读取数据
	if(0 == pid)
	{
		while(1)
		{
			memset(buf, 0, sizeof(buf));
			read(fd[0], buf, sizeof(buf));	//默认是阻塞的
			printf("readbuf:%s", buf);
		}
	}
	
	return 0;
}


4、命名管道

命名管道与一般管道要一些不同点
1) 命名管道是在文件系统中作为一个特殊的设备文件而存在的。
2) 不同管道的进程之间可以通过命名管道共享数据。
3) 当共享命名管道的进程执行完所有的 I/O 操作后,命名管道将继续保存在文件系统中,以便以后使用。
4) 普通管道只能由父子兄弟相关进程使用,它共同的祖先进程创建了管道。但是,通过命名管道,不相关的进程也能交换数据。
5) 一旦用mkfifo函数创建了一个命名管道,就可以 open 打开它。一般的文件 I/O 函数( close , read , write , unlink )都可用于命名管道。

函数头文件:
#include <sys/types.h>
#include <sys/stat.h>
函数原型:
int mkfifo(const char * pathname,mode mode)
pathname: 管道文件名
mode: 管道创建方式
函数返回值:
成功: 0
失败: -1

代码例程:

读端代码

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

#define  FIFO_PATH  "/home/gec/myfifo"
/*有名管道读端程序*/
int main(int argc, char *argv[])
{
	//1, 判断有名管道是否存在 --> 不存在则创建
	if( access(FIFO_PATH, F_OK) != 0)	//access返回值不等于0,表示文件不存在
	{
		int ret = mkfifo(FIFO_PATH, 0777);
		if(-1 == ret)
		{
			perror("mkfifo failed");
			return -1;
		}
	}
	
	//2, 直接打开有名管道 --> open()
	int fd = open(FIFO_PATH, O_RDWR);
	if(-1 == fd)
	{
		perror("open failed");
		return -1;
	}
	
	//3, 循环获取读取管道中数据	--> "EXIT\n"
	char buf[128];
	while(1)
	{
		memset(buf, 0, sizeof(buf));
		read(fd, buf, sizeof(buf));
		if( strcmp("EXIT\n", buf) == 0 )
			break;
		printf("readbuf:%s", buf);
	}
	//4, 关闭管道文件
	close(fd);	
	return 0;
}

写端代码

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

#define  FIFO_PATH  "/home/gec/myfifo"

/*有名管道写端程序*/
int main(int argc, char *argv[])
{
	//1, 判断有名管道是否存在 --> 不存在则创建
	if( access(FIFO_PATH, F_OK) != 0)	//access返回值不等于0,表示文件不存在
	{
		int ret = mkfifo(FIFO_PATH, 0777);
		if(-1 == ret)
		{
			perror("mkfifo failed");
			return -1;
		}
	}
	
	//2, 直接打开有名管道 --> open()
	int fd = open(FIFO_PATH, O_RDWR);
	if(-1 == fd)
	{
		perror("open failed");
		return -1;
	}
	
	//3, 循环获取数据写入管道
	char buf[128];
	while(1)
	{
		memset(buf, 0, sizeof(buf));
		fgets(buf, sizeof(buf), stdin);
		write(fd, buf, sizeof(buf));
		if( strcmp("EXIT\n", buf) == 0 )
			break;
	}
	//4, 关闭管道文件
	close(fd);
	
	return 0;
}



标签:int,编程,管道,fd,第二节,sizeof,include,buf
来源: https://blog.csdn.net/lianggoch/article/details/118884668

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有