LInux管道实现进程间通信及实例说明

发布于:2023-01-23 ⋅ 阅读:(408) ⋅ 点赞:(0)

目录

一、管道

二、管道的类型

1、无名管道

2、有名管道

三、管道的创建

1、无名管道的创建

2、有名管道的创建

四、实例说明

1、无名管道实例

2、有名管道实例

(1)、创建管道文件

(2)、写文件

(3)、读文件


一、管道

        管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入,Linux的管道主要包括两种:无名管道和有名管道。

二、管道的类型

1、无名管道

1、只能用于具有亲缘关系的进程之间的通信

2、是一个单工的通行模式,具有固定的读端和写端

3、创建之后存在于内核中,在文件系统中不可见

读写特性:

        读特性:
                写端存在:
                        管道有数据:返回读到的字节数
                        管道无数据:程序阻塞
    
                写段不存在:
                        管道有数据:返回读到的字节数
                        管道无数据:返回0
            

        写特性:
                读端存在:
                        管道有空间:返回写入的字节数
                        管道无空间:程序阻塞,直到有空间为止
            
                读端不存在:
                        无论管道是否有空间,管道破裂,管道破裂进程终止

2、有名管道

1、可用于任意类型的进程之间

2、双工通信,没有固定的读端或者写端

3、创建之后可在文件系统中查看到

读写特性:

        适用所有情况

三、管道的创建

1、无名管道的创建

头文件:

        #include <unistd.h>

        int pipe(int pipefd[2]);

参数:

        pipefd:存放无名管道读端和写端的数组首地址

        pipefd[0]——读端
        pipefd[1]——写端

返回值:

        成功返回0,失败返回-1

2、有名管道的创建

头文件:

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

函数原型:

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

参数:

        pathname:创建管道文件的文件名

        mode:创建管道文件的权限


返回值:

        成功返回0,失败返回1

四、实例说明

1、无名管道实例

利用管道实现子进程输入,父进程输出

/*===============================================================
 *   Copyright (C) 2022 All rights reserved.
 *   
 *   文件名称:comunication.c
 *   创 建 者:QiuCC
 *   创建日期:2022年08月10日
 *   描    述:利用无名管道实现子进程输入,父进程输出
 *
 *   更新日志:
 *
 ================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define N 100


int main(int argc, char *argv[])
{
	int pipefd[2] = {0};//pipefd[0]存放管道的读端,pipefd[1]存放管道的写端
	int ret;
	ret = pipe(pipefd);

	pid_t pid = fork();//创建子进程

	if(-1 == pid){
		perror("fork");
		exit(-1);
	}

	if(ret == -1){
		perror("pipe");
		exit(-1);
	}

	if(pid == 0){//子进程
		while(1){
			char str[N];
			fgets(str, N, stdin);//从终端获取数据
			str[strlen(str) - 1] = '\0';
			write(pipefd[1], str, N);//将数据写入管道
		}
	}else{
		while(1){
			char str[N];
			read(pipefd[0], str, N);//将管道内容读入
			puts(str);//向终端输出数据
		}
		wait(NULL);//等待子进程结束
	}

	return 0;
}

运行结果如图:子进程输入一个,父进程打印一个

2、有名管道实例

通过有名管道,实现一个程序输入,另一个程序输出

(1)、创建管道文件

/*===============================================================
*   Copyright (C) 2022 All rights reserved.
*   
*   文件名称:mkfifo.c
*   创 建 者:QiuCC
*   创建日期:2022年08月10日
*   描    述:利用mkfifo()函数创建管道文件
*
*   更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#define N 100

int main(int argc, char *argv[])
{
	int ret = mkfifo("fifo", 0664);//创建管道文件
	if(ret == -1){
		perror("mkfifo");
	}

	return 0;
}

(2)、写文件

/*===============================================================
 *   Copyright (C) 2022 All rights reserved.
 *   
 *   文件名称:in.c
 *   创 建 者:QiuCC
 *   创建日期:2022年08月10日
 *   描    述:创建文件实现向管道写入的功能
 *
 *   更新日志:
 *
 ================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define N 100

int main(int argc, char *argv[])
{
	int fd = open("fifo", O_WRONLY);//以只写方式打开管道文件
	if(fd == -1){
		perror("open fifo");
		exit(-1);
	}

    printf("I am in.c\n");
	while(1){	
		char str[N] = {0};
		fgets(str, N, stdin);
		str[strlen(str)-1] = '\0';
		write(fd, str, strlen(str));//向管道文件写入数据
	}

	return 0;
}

(3)、读文件

/*===============================================================
 *   Copyright (C) 2022 All rights reserved.
 *   
 *   文件名称:out.c
 *   创 建 者:QiuCC
 *   创建日期:2022年08月10日
 *   描    述:从管道文件读取数据并输出到终端
 *
 *   更新日志:
 *
 ================================================================*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#define N 100

int main(int argc, char *argv[])
{
	int fd = open("fifo", O_RDONLY);//以只读方式打开管道文件
	if(fd == -1){
		perror("open fifo");
		exit(-1);
	}

	while(1){
		char str[N] = {0};
		int ret  = read(fd, str, N);//从管道文件读取数据
		if(ret == -1){
			perror("read");
			exit(-1);
		}
		puts(str);//输出到终端
	}

	return 0;
}

        通过上述三个程序,我们先编译运行创建管道的文件,会发现此时有一个名为fifo的管道文件生成,显示具体信息,文件类型为管道文件。

        

        我们接着编译in.c和out.c

        我们此时打开一个另一个终端,我们先单独运行./in 。

        此时我们发现,我们的终端处于等待状态,但是,我们在输入前准备输出的话“I am in.c”并没有输出。

        我们接着在另一个终端运行./out,此时我们的“I am in.c”打印并输出,可见,我们的有名管道必须两端同时打开才有效。

         我们接着输入数据,我们in输入一个,out就打印一个,可见我们的管道实现了两个文件之间的通信,也就是两个独立进程之间的通信。

好的,以上就是本期内容,欢迎大家参考,指正!!!


网站公告

今日签到

点亮在社区的每一天
去签到