• Linux14 -- 进程间通信、管道


    一、进程间通信

    前言

    进程间通信

    进程间通信的方法

    (1)管道
    (2)信号量
    (3)共享内存
    (4)消息队列
    (5)套接字

    你了解的IPC机制都有哪些?

    二、管道

    1、管道简介

    | 命令:
    举例:ps -ef | grep “sleep”
    两个进程通信,比如a,b进程,a向管道中写入数据,b读取数据;
    在这里插入图片描述
    管道的分类:有名管道和无名管道
    区别
    有名管道在任意两个进程间通信,
    无名管道在父子进程间通信;

    2、有名管道的创建

    创建的命令:mkfifo
    打开管道:open();
    读数据:read();
    写入数据:write();
    关闭管道:close();

    3、相关思考

    如果进程 a 要将从键盘获取的数据传递给另一个进程 b, 用已具备的知识思考应该如何完成 ?

    创建管道之后,它会在内存上分配一块空间,表面上看把数据写入管道中了,实际上是把数据写入内存中了。另外一个程序是从内存中读取数据的,所以效率是比较高的。

    管道文件:大小永远为0;

    4、有名管道实现进程间通信

    又名命名管道;

    代码实现:

    a.c
    //a.c
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    int main()
    {
    	int fd=open("fifi",O_WRONLY);
    	assert(fd!=-1);
    	printf("fd=%d\n",fd);
    	write(fd,"hello",5);
    	close(fd);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    b.c
    //b.c
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    int main()
    {
    	int fd=open("./fifi",O_RDONLY);
    	assert(fd!=-1);
    	printf("fd=%d\n",fd);
    	char buff[128]={0};
    	read(fd,buff,127);
    	printf("read:%s\n",buff);
    	close(fd);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    5、管道的特点:

    (1)管道必须读,写进程同时open,否则会阻塞;
    (2)如果管道中没有数据,那么read就会阻塞;
    (3)管道的写端关闭,读read返回值为0;
    (4)管道打开的时候只有只读和只写方式,读写方式是未定义的;

    6、将上面的代码改为循环

    a.c

    //a.c
    #include 
    #include 
    #include 
    int main()
    {
    	int fd=open("fifi",O_WRONLY);
    	assert(fd!=-1);
    	while(1)
    	{
    		printf("input:\n");
    		char buff[128]={0};
    		fgets(buff,128,stdin);
    		if(strncmp(buff,"end",3)==0)
    		{
    			break;
    		}
    		write(fd,buff,strlen(buff));
    	}
    	close(fd);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    b.c

    //b.c
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    int main()
    {
    	int fd=open("./fifi",O_RDONLY);
    	assert(fd!=-1);
    	printf("fd=%d\n",fd);
    	while(1)
    	{
    		char buff[128]={0};
    		if( read(fd,buff,127)==0)
    		{
    			break;
    		}
    		printf("read:%s\n",buff);
    	}
    	close(fd);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    7、无名管道的介绍

    使用pipe创建无名管道,只能进行父子间的通信;

    pipe是一个系统调用

    int pipe(int fds[2]);
    //pipe()成功返回 0,失败返回-1
    //fds[0]是管道读端的描述符
    // fds[1]是管道写端的描述符
    //规定
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代码演示:

    父进程写入数据,子进程读取数据;

    #include 
    #include 
    #include 
    #include 
    #include 
    int main()
    {
    	int fd[2];
    	assert(pipe(fd)!=-1);
    	pid_t pid=fork();//先open,再frok,父子进程共享打开的文件描述符
    	assert(pid!=-1);
    	if(pid==0)
    	{
    		close(fd[1]);
    		char buff[128]={0};
    		read(fd[0],buff,127);
    		printf("child read:%s\n",buff);
    		close(fd[0]);
    	}
    	else
    	{
    		close(fd[0]);
    		write(fd[1],"hello",5);
    		close(fd[1]);
    	}
    	exit(0);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    8、管道的特点:

    (1)管道必须读,写进程同时open,否则会阻塞;
    (2)如果管道中没有数据,那么read就会阻塞;
    (3)管道的写端关闭,读read返回值为0;
    (4)管道打开的时候只有只读和只写方式,读写方式是未定义的;
    (5)管道是半双工的(某一时刻只能选择一个方向)(面试重点)、(通信方式有单工,半双工,全双工)
    (6)无论有名还是无名,写入管道的数据都在内存中(面试重点)
    (7)有名管道和无名管道的区别:(面试重点)
    有名可以在任意进程间通信
    无名主要在父子进程间通信
    (8)管道的读端关闭,写会产生异常(发送信号SIGPIPE)(可以改变信号的响应方式验证一下)

    9、管道的实现

    在这里插入图片描述

  • 相关阅读:
    vue-treeselect树形下拉,根据登录人角色,隐藏本级登录人节点(树形数据,删除指定节点)
    实现两个div水平对齐
    【微服务部署】九、使用Docker Compose搭建高可用双机热备MySQL数据库
    Find My资讯|首款支持苹果Find My电动滑板车发布
    166 个最常用的 Linux 命令汇总,总有你需要用到的...
    Java Web 学习笔记(三) —— Maven 基础
    164_技巧_Power Query 之巧解-外部表不是预期的格式
    python基础(五)----时间模块
    Socks5代理、IP代理与网络安全:保护你的爬虫和隐私
    .net core基于HttpClient实现的网络请求库
  • 原文地址:https://blog.csdn.net/kyrie_sakura/article/details/127675710