Linux下的系统编程——进程间的通信(九)

这篇具有很好参考价值的文章主要介绍了Linux下的系统编程——进程间的通信(九)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言: 

前面我们已经对进程已经有了一个简单的了解与认识,那么进程间的通信是什么样的呢,什么是父子进程,什么是兄弟进程,没有血缘关系间的进程是如何实现进程通信的,下面让我们一起学习一下什么是进程间的通信吧。

目录

一、进程间通信常用方式

IPC方式:

二、管道

1.概念:

*2.pipe函数:

*3.管道的读写行为:

4.父子间进程 :

 5.兄弟间进程通信:

6.多个读写端操作管道

7.管道缓冲区大小:

.8.管道的优劣

 三、FIFO:   

1.命名管道fifo的创建和原理:

 2.非血缘关系进程间通信avi:


一、进程间通信常用方式

IPC方式:

        Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。
 

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

        在进程间完成数据传递需要借助操作系统提供特殊的方法,如:文件、管道、信号、共享内存、消息队列、套接字、命名管道等。随着计算机的蓬勃发展,一些方法由于自身设计缺陷被淘汰或者弃用。现今常用的进程间通信方式有:


1.管道(使用最简单)

2.FIFO(无血缘关系,单次读取)

3.共享映射区(无血缘关系,反复读取)

4.信号(开销最小)

5.本地套接字(最稳定)

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

二、管道

1.概念:

      

         管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质:


(1).其本质是一个伪文件(实为内核缓冲区)

(2).由两个文件描述符引用,一个表示读端,一个表示写端,只能一次读取

(3).规定数据从管道的写端流入管道,从读端流出,单向流动


管道的原理:  管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现

管道的:

        1)数据不能进程自己写,自己读。·

        2)管道中数据不可反复读取。一旦读走,管道中不再存在。

        3)采用半双工通信方式,数据只能在单方向上流动

        4)只能在有公共祖先的进程间使用管道

常用的通信方式: 单工通信、半双工通信、全双工通信

创建管道文件:

(不占用磁盘空间)

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

*2.pipe函数:

pipe函数:用于有血缘关系的进程间通信

函数功能:创建,并打开管道。

    int pipe(int fd[2]);

    参数:    

        fd[0]: 读端。

        fd[1]: 写端。

    返回值:

         成功: 0

         失败: -1 errno

管道通信:

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}


int main(int argc, char *argv[])
{
	int ret,re;
	int fd[2];
	pid_t pid;
	char *str = "hello pipe\n";
	char buf[1024];

	ret = pipe(fd);     //父进程先创建一个管道,持有管道的读端和写端
	if(ret == -1)
		sys_err("pipe error");
	
	pid = fork();        //子进程同样持有管道的读和写端

	if(pid > 0){            //父进程
		close(fd[0]);       //关闭读段
		write(fd[1],str,strlen(str));//写入数据
        sleep(1);
		close(fd[1]);            //关闭写段
	}else if(pid == 0){        //子进程
		close(fd[1]);          //关闭写段
		re = read(fd[0],buf,sizeof(buf)); //读取数据
		write(STDOUT_FILENO,buf,re);      //写到屏幕上
		close(fd[0]);        //关闭读段
	}

	return 0;

}

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

*3.管道的读写行为:

读管道:
        1. 管道有数据,read返回实际读到的字节数。

        2. 管道无数据:    

                        1)无写端,read返回0 (类似读到文件尾)

                        2)有写端,read阻塞等待。

写管道:
        1. 无读端, 异常终止。 (SIGPIPE导致的)

        2. 有读端:    

                        1) 管道已满, 阻塞等待(少见)

                        2) 管道未满, 返回写出的字节个数。

 1)读管道,管道无数据(无写端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}


int main(int argc, char *argv[])
{
	int ret,re;
	int fd[2];
	pid_t pid;
	char *str = "hello pipe\n";
	char buf[1024];

	ret = pipe(fd);    //父进程先创建一个管道,持有管道的读端和写端
	if(ret == -1)
		sys_err("pipe error");
	
	pid = fork();        //子进程同样持有管道的读和写端

	if(pid > 0){            //父进程
		close(fd[0]);       //关闭读段
	//	write(fd[1],str,strlen(str));//写入数据
		close(fd[1]);            //关闭写段
	}else if(pid == 0){        //子进程
		close(fd[1]);          //关闭写段
		re = read(fd[0],buf,sizeof(buf)); //读取数据
		
		printf("child read ret =%d\n",ret);
		
		write(STDOUT_FILENO,buf,re);      //写到屏幕上
		close(fd[0]);        //关闭读段
	}

	return 0;

}

read返回0

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

*4.父子间进程通信 :

        使用管道实现父子进程间通信,完成:ls | wc -l。假定父进程实现ls,子进程实现wc

ls | wc -l命令:

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

 实现流程:

(1)父进程创建管道 pipe()

(2)父进程创建子进程 fork()

(3)设置父进程执行ls命令,子进程执行wc命令 execlp()

(4)设置父子进程通过管道的单项流动(设置指向标准输出的指向管道dup2()

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}

int main(int argc,char *argv[])
{
	/***************
		dup2();
		fork();
		pipe();
		execlp();
	****************/
	int fd[2]; 
	int ret;
	pid_t pid;

    //父进程创建管道
	ret = pipe(fd);     //父进程先创建一个管道,持有管道的读端和写端
	if(ret == -1){
		sys_err("pipe error");
	}

    //父进程创建子进程 
	pid = fork();        //子进程同样持有管道的读和写端

	if(pid == -1){
		sys_err("fork error");
	}else if(pid > 0){                     //父进程 读,关闭写端
		close(fd[1]);                      //关闭写,设置单项流动
		dup2(fd[0],STDIN_FILENO);          //设置读管道信息,重定向stdin 到管道读端
		execlp("wc","wc","-l",NULL);       //设置父进程wc命令
		sys_err("execlp wc error");
	}else if(pid == 0){
		
        close(fd[0]);                      //关闭读,设置单项流动
		dup2(fd[1],STDOUT_FILENO);         //设置写操作指向管道,重定向stdout 到管道写端
		execlp("ls","ls",NULL);            //设置子进程执行ls命令 
		sys_err("execlp ls error");
	}

	return 0;
}

 Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

 5.兄弟间进程通信:

使用管道实现兄弟进程间通信,完成:ls | wc -l。假定父进程实现ls,子进程实现wc

 实现流程:

(1)父进程创建管道 pipe()

(2)父进程创建俩个(兄弟)子进程 fork()

(3)设置兄进程执行ls命令,第进程执行wc命令 execlp() 

(4)设置兄弟进程通过管道的单项流动(设置指向标准输出的指向管道dup2()

(5)回收父进程残余文件  wait()

刚创建出的兄弟进程:

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

 设置兄弟进程通过管道的单项流动后

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}

int main(int argc,char *argv[])
{
	/***************
		dup2();
		fork();
		pipe();
		execlp();
        wait();
	****************/
	int fd[2]; 
	int ret;
	int i;
	pid_t pid;

    //父进程创建管道
	ret = pipe(fd);
	if(ret == -1){
		sys_err("pipe error");
	}

	for(i = 0;i < 2;i++){              //表达式2 出口,仅限父进程使用
		pid = fork();
		if(pid == -1){
			sys_err("fork error");
		}
		if(pid == 0)                   //子进程出口
			break;
	}



	if(i == 2){                        //父进程 不参与管道使用
        //不需要父进程所以需要关闭他管道的读写端
		close(fd[0]);          
		close(fd[1]);
        //回收子进程
		wait(NULL);
		wait(NULL);
	}else if(i == 0){                  //兄进程
		close(fd[0]);
		dup2(fd[1],STDOUT_FILENO);     //重定向stdout
		execlp("ls","ls",NULL);        //兄进程执行ls命令
		sys_err("ececlp ls error");
	}else if(i == 1){		           //弟进程
		close(fd[1]);
		dup2(fd[0],STDIN_FILENO);      //重定向stdin
		execlp("wc","wc","-l",NULL);   //弟进程执行wc命令
		sys_err("ececlp wc error");
	}

	return 0;
}

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

6.多个读写端操作管道

实现一个pipe有一个写端,多个读端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}

int main(int argc,char *argv[])
{
	/***************
		dup2();
		fork();
		pipe();
		execlp();
	****************/
	int fd[2],i,n; 
	int ret;
	char buf[1024];
	pid_t pid;

    //父进程创建管道
	ret = pipe(fd);
	if(ret == -1){
		sys_err("pipe error");
		exit(1);
	}

	for(i = 0;i < 2;i++){
		pid = fork();
		if(pid == -1){
			sys_err("fork error");
			exit(1);
		}
		if(pid == 0)
			break;
	}


	if(i == 2){            //父进程
		close(fd[1]);       //父进程关闭写端,留读端读取数据
		sleep(1);
		n = read(fd[0],buf,1024);    //从管道中读取数据
		write(STDOUT_FILENO,buf,n); 
 
		for(i == 0;i < 2;i++)        //两个儿子wait两次
			wait(NULL);

	}else if(i == 0){        //兄进程
		close(fd[0]);
		write(fd[1],"1.hello\n",strlen("1.hello\n"));
	}else if(i == 1){		 //弟进程
		close(fd[0]);
		write(fd[1],"2.world\n",strlen("2.world\n"));
	}

	return 0;
}

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

7.管道缓冲区大小:

可以使用 ulimIt -a 命令来查看当前系统中创建管道文件所对应的内核缓冲区大小。通常为:
        pipe size               ......(512 bytes,-p)  8 

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

也可以使用fpathconf函数,借助参数―选项来查看。使用该宏应引入头文件<unistd.h>
        long fpathconf(int fd, int name);成功:返回管道的大小―失败:-1,设置errno

.8.管道的优劣

优点:简单,相比信号,套接字实现进程间通信,简单很多。

缺点:

                1.只能单向通信,双向通信需建立两个管道。
                2.只能用父子、兄弟进程(有共同祖先)间通信。该问题后来使用fifo有名管道解决)

 三、FIFO:   

fifo管道:可以用于无血缘关系的进程间通信。

    命名管道:  mkfifo 

    无血缘关系进程间通信:

                        读端,open fifo O_RDONLY

                        写端,open fifo O_WRONLY

     

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

1.命名管道fifo的创建和原理:

使用命令:myfifo myfifo

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

 使用myfifo创建

#include<stdio.h>
#include<sys/stat.h>
#include<errno.h>
#include<pthread.h>
#include<stdlib.h>


void sys_err(const char *str){
	perror(str);
	exit(1);
}

int main(int argc,char *str)
{
	int ret = mkfifo("mytestfifo",0664);
	if(ret == -1)
		sys_err("mkfifo error");

	return 0;
	
}

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

 2.非血缘关系进程间通信avi:

向管道写数据fifo_w.c

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

void sys_err(char *str)
{
    perror(str);
    exit(-1);
}

int main(int argc, char *argv[])
{
    int fd, i;
    char buf[4096];

    if (argc < 2) {
        printf("Enter like this: ./a.out fifoname\n");
        return -1;
    }
    fd = open(argv[1], O_WRONLY);       //打开管道文件
    if (fd < 0) 
        sys_err("open");

    i = 0;
    while (1) {
        sprintf(buf, "hello itcast %d\n", i++);

        write(fd, buf, strlen(buf));    // 向管道写数据
        sleep(1);
    }
    close(fd);

    return 0;
}

 向管道读数据fifo_r.c

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

void sys_err(char *str)
{
    perror(str);
    exit(1);
}

int main(int argc, char *argv[])
{
    int fd, len;
    char buf[4096];

    if (argc < 2) {
        printf("./a.out fifoname\n");
        return -1;
    }


    fd = open(argv[1], O_RDONLY);   // 打开管道文件
    if (fd < 0) 
        sys_err("open");
    while (1) {
        len = read(fd, buf, sizeof(buf));   // 从管道的读端获取数据
        write(STDOUT_FILENO, buf, len);
        sleep(3);           //多個读端时应增加睡眠秒数,放大效果.
    }
    close(fd);

    return 0;
}

一方写,一方读:

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数

一个写,多个读:管道特性,不能反复读取

Linux下的系统编程——进程间的通信(九),linux,IPC方式,管道,进程间通信,Linux系统编程,pipe函数文章来源地址https://www.toymoban.com/news/detail-696894.html

到了这里,关于Linux下的系统编程——进程间的通信(九)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux--进程间的通信--进程池

    进程间的通信–匿名管道 进程池是一种将多个进程组织起来以执行特定任务的机制 。 它由多个预先创建好的资源进程和一个管理进程组成。这些资源进程被管理进程负责分配和调度,用于处理任务 。 当有新的任务提交时,管理进程会从进程池中取出一个资源进程,将任务

    2024年04月25日
    浏览(26)
  • 《Linux操作系统编程》 第六章 Linux中的进程监控: fork函数的使用,以及父子进程间的关系,掌握exec系列函数

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月11日
    浏览(26)
  • Linux--进程间的通信-共享内存

    前文: Linux–进程间的通信-匿名管道 Linux–进程间的通信–进程池 Linux–进程间的通信-命名管道 对于两个进程,通过在内存开辟一块空间(操作系统开辟的),进程的虚拟地址通过页表映射到对应的共享内存空间中,进而实现通信 ; 特点和作用: 高效性: 共享内存是一种

    2024年04月26日
    浏览(28)
  • Linux--进程间的通信-匿名管道

    进程间通信(IPC,Interprocess Communication)是指在不同进程之间传输数据和交换信息的一种机制。它允许多个进程在同一操作系统中同时运行,并实现彼此之间的协作 。 进程间通信方式: 管道(Pipe) : 管道是最基本的进程间通信方式 ,它是一种 半双工 的通信方式,通过管

    2024年04月14日
    浏览(32)
  • 【Linux】进程间的通信之共享内存

    利用 内存共享 进行进程间的通信的原理其实分为以下几个步骤: 在物理内存中创建一块共享内存。 将共享内存链接到要通信的进程的页表中,并通过页表进行进程地址空间的映射。 进程地址空间映射完毕以后返回首个虚拟地址,以便于进程之间进行通信。 根据共享内存的

    2024年02月09日
    浏览(37)
  • Linux下的系统编程——进程的执行与回收(八)

    前言: 前面我们对进程已经有了一个初步的了解与认识,现在让我们学习一下进程中一些函数的具体使用,比如exec可以执行一些指定的程序,wait / waitpid可以回收子进程,什么是孤儿进程,什么是僵尸进程,下面让我们一起对这些进行中的操作进行学习吧 目录 一、exec函数族

    2024年02月09日
    浏览(37)
  • Linux系统编程——进程间通信的学习

    学习参考博文: 进程间的五种通信方式介绍 Linux 信号介绍 Linux系统编程学习相关博文 Linux系统编程——文件编程的学习 Linux系统编程——进程的学习 Linux系统编程——线程的学习 Linux系统编程——网络编程的学习 常规学习Linux系统编程的内容是复杂且繁多的,不推荐刚开始

    2024年02月08日
    浏览(29)
  • Linux系统编程:采用管道的方式实现进程间通信

    目录 一. 进程间通信概述 二. 管道的概念  三. 通过管道实现进程间通信 3.1 实现原理 3.2 匿名管道创建系统接口pipe 3.3 管道通信的模拟实现 3.4 管道通信的访问控制规则 3.5 管道通信的特点 四. 通过匿名管道实现进程池 4.1 进程池的概念 4.2 进程池的模拟实现 五. 命名

    2024年02月12日
    浏览(30)
  • 环境编程代码实例:进程间通信(IPC)

    环境编程代码实例:进程间通信(IPC)。 yezhening/Environment-and-network-programming-examples: 环境和网络编程实例 (github.com) Environment-and-network-programming-examples: 环境和网络编程实例 (gitee.com) 低级:3种 全局变量/glov:类似管道、命名管道、消息队列、共享内存:头文件/库文件全局变量

    2024年02月05日
    浏览(26)
  • 【linux 多线程并发】多线程模型下的信号通信处理,与多进程处理的比较,属于相同进程的线程信号分发机制

    ​ 专栏内容 : 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发,开发的

    2024年01月17日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包