进程间通信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 <unistd.h>

			   int pipe(int pipefd[2]);
			   
		函数功能: 创建一个无名管道pipe 并返回两个文件描述符 
		
		头文件: 如上 
		
		参数列表: 
				
				pipefd: 是一个具有两个int类型元素大小的数组 
						用来保存返回的两个文件描述符  
						pipefd[0] 保存读的文件描述符 
						pipefd[1] 保存写的文件描述符		
		返回值: 
				成功返回0 
				失败返回-1 并且errno被设置

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

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

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;
}

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

fifo的创建则为: 
			
			NAME
				   mkfifo - make a FIFO special file (a named pipe)

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

				   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被设置
fifo的创建有两种形式: 
			
			1.通过如上的函数mkfifo 
		
					mkfifo("/home/china/test.fifo",0666);
					
			2.通过指令命令mkfifo

					mkfifo ~/test.fifo  
					

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

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

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

猜你喜欢

转载自blog.csdn.net/weixin_46836491/article/details/126813475
今日推荐