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

12 篇文章 0 订阅
10 篇文章 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就打印一个,可见我们的管道实现了两个文件之间的通信,也就是两个独立进程之间的通信。

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

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一个使用Linux进程间通信(IPC)机制的示例代码,包括使用管道(pipe)、共享内存(shared memory)和信号量(semaphore)进行进程间通信。 1. 使用管道(pipe)进行进程间通信: ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define BUFFER_SIZE 25 int main() { int fd[2]; pid_t pid; char write_msg[BUFFER_SIZE] = "Greetings"; char read_msg[BUFFER_SIZE]; if (pipe(fd) == -1) { fprintf(stderr, "Pipe failed"); return 1; } pid = fork(); if (pid < 0) { fprintf(stderr, "Fork failed"); return 1; } if (pid > 0) // Parent process { close(fd[0]); write(fd[1], write_msg, BUFFER_SIZE); close(fd[1]); } else // Child process { close(fd[1]); read(fd[0], read_msg, BUFFER_SIZE); printf("Received message: %s\n", read_msg); close(fd[0]); } return 0; } ``` 2. 使用共享内存(shared memory)进行进程间通信: ``` #include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #define SHM_SIZE 1024 int main() { int shmid; key_t key = 1234; char *shm, *s; if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666)) < 0) { perror("shmget"); exit(1); } if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) { perror("shmat"); exit(1); } printf("Enter message: "); for (s = shm; (*s = getchar()) != '\n'; s++) ; *s = '\0'; printf("You entered: %s\n", shm); shmdt(shm); return 0; } ``` 3. 使用信号量(semaphore)进行进程间通信: ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/sem.h> #define MAX_RETRIES 10 union semun { int val; struct semid_ds *buf; unsigned short *array; }; int main() { key_t key = 1234; int semid, semval; union semun arg; struct sembuf sembuf; if ((semid = semget(key, 1, IPC_CREAT | 0666)) == -1) { perror("semget"); exit(1); } arg.val = 1; if (semctl(semid, 0, SETVAL, arg) == -1) { perror("semctl"); exit(1); } if ((semval = semctl(semid, 0, GETVAL, 0)) == -1) { perror("semctl"); exit(1); } printf("Semaphore value before decrement: %d\n", semval); sembuf.sem_num = 0; sembuf.sem_op = -1; sembuf.sem_flg =

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玖尾猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值