• 进程间通信IPC-管道


    IPC :Internal Processes Communication

    进程间通信 实现:(信息)数据的交换
    管道: pipe 无名管道
    fifo 有名管道

    信号: signal

    消息队列 System V 消息队列 / POSIX消息队列(两套不同的机制)

    信号量 System V 信号量 / POSIX 信号量

    共享内存 System V 共享内存 / POSIX 共享内存

    socket通信: Unix域协议

    在以前进程间通信的方式 都是通过文件!
    但是这种方式 他有一个缺点: 他的效率太低了

    管道

    无名管道 pipe
    管道虽然是一个文件 但是它在文件系统中没有名字(没有inode)
    他的内容是在内核中 访问pipe的方式还是通过文件系统的API函数(read/write)
    但是它又不能用open(因为它没有名字 ) 问题是read/write又需要一个文件描述符才能对文件进行操作。
    所以在创建pipe的时候 就必须要返回文件描述符!
    pipe在创建的时候 在内核中开辟一块缓冲区 作为pipe文件内容的存储空间 同时返回两个文件描述符(一个用来读 一个用来写)
    它还有如下特点:
    (1)pipe有两端 一端用来写 一端是用来读
    (2)按顺序读 不支持lseek
    (3)内容读走了 就没有了
    (4)pipe(无名管道)随进程持续性

    NAME
    			   pipe - create pipe
    
    		SYNOPSIS
    			   #include 
    
    			   int pipe(int pipefd[2]);
    			   
    		函数功能: 创建一个无名管道pipe 并返回两个文件描述符 
    		
    		头文件: 如上 
    		
    		参数列表: 
    				
    				pipefd: 是一个具有两个int类型元素大小的数组 
    						用来保存返回的两个文件描述符  
    						pipefd[0] 保存读的文件描述符 
    						pipefd[1] 保存写的文件描述符		
    		返回值: 
    				成功返回0 
    				失败返回-1 并且errno被设置
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    使用管道实现进程间通信
    进程间可以利用全局变量通信吗?
    不行!全局变量不共享,相当于进程只是把该变量复制了一份

    #include
    #include
    #include
    #include
    #include
    #include
    
    void sys_err(char *str)
    {
        perror(str);
        exit(1);
    }
    
    int main(int argc,char * argv[])
    {
        int ret;
        int fd[2];  //fd[0]是读端 fd[1]是写段
        char *str="hello!!!\n";
        char buf[1024];
        ret=pipe(fd);
        if(ret==-1)
        {
            sys_err("pipe error\n");
        }
        pid_t pid =fork();
        if(pid == 0) //子进程
        {
            close(fd[1]); //关闭写端
            ret=read(fd[0],buf,sizeof(buf)); //从管道中读到数据 存在buf中
            write(STDOUT_FILENO,buf,ret); //在终端读出数据
            close(fd[0]); //关闭读端
        }
        else //父进程
        {
            close(fd[0]); //关闭读端
            write(fd[1],str,strlen(str));  //把数据写入管道中
            sleep(1);
            close(fd[1]); //关闭写端
        }
        return 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    有名管道 fifo
    fifo是在pipe地基础上 给fifo在文件系统中创建一个inode(他会在文件系统中有一个文件名)
    但是同样地 fifo文件地内容却是在内核中

    fifo的创建则为: 
    			
    			NAME
    				   mkfifo - make a FIFO special file (a named pipe)
    
    			SYNOPSIS
    				   #include 
    				   #include 
    
    				   int mkfifo(const char *pathname, mode_t mode);
    				   
    				   函数功能: 创建一个有名管道 
    				   
    				   头文件: 如上 
    				   
    				   参数列表: 
    							pathname : 你要创建的有名管道的路径名  
    									   注意:不要创建在共享文件夹下 windows不支持fifo 
    									   
    							mode: 创建的有名管道的权限 有两种方式指定: 
    								  a. S_IRUSR S_IWUSR S_IXUSR S_IRGRP ... 
    								  b. 0660 
    								  
    				   返回值: 
    							成功返回0 
    							失败返回-1 并且errno被设置
    
    • 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
    fifo的创建有两种形式: 
    			
    			1.通过如上的函数mkfifo 
    		
    					mkfifo("/home/china/test.fifo",0666);
    					
    			2.通过指令命令mkfifo
    
    					mkfifo ~/test.fifo  
    					
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    FIFO(有名管道)和PIPE(无名管道)类似,除了他在文件系统中有一个名字,它可以被多个进程打开用来读或写
    当进程用FIFO来交换数据时 内核根本没有把数据写到文件系统中 而是保存在内核的内部 因此FIFO在文件系统中根本没有内容 它仅作为文件系统的一个引用入口 提供一个文件名 给其他进程去open它

    在数据交换前 FIFO的两端(read/write)必须都被打开
    通常情况下 你打开FIFO的一端 会阻塞 直到另外一端也被打开

    一个进程同样可以以“非阻塞”方式(O_NONBLOCK)去打开 在这种情况下,只读打开总会成功 即便是写端没有被打开
    只写打开总会失败 并且errno == EENXIO 除非读端已经打开

  • 相关阅读:
    MySQL高可用方案之MHA
    C#NPOI操作Excel,实现Excel数据导入导出(支持多个sheet)
    stm32 cubeide 闪退 显示self upgrade failed
    云服务器和CDN有什么区别?
    vue3 setup 语法糖,父子传参
    k8s存储:卷、持久卷、存储类
    Java阻塞队列中的异类,SynchronousQueue底层实现原理剖析
    语义检索系统【全】:基于Milvus+ERNIE+SimCSE+IBN实现学术文献语义检索系统完整版
    物联网_01_物理设备的网络接入
    【面试经验包】面试被吊打经验总结
  • 原文地址:https://blog.csdn.net/weixin_46836491/article/details/126813475