Linux进程间通信

Posted Huang_ZhenSheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux进程间通信相关的知识,希望对你有一定的参考价值。

目录

匿名管道:

代码演示: 

管道的特性: 

验证部分特性: 

管道大小

命名管道:

命令行代码实验:

命名管道实现的相关代码:

Client端:

server端:

makefile:

运行结果:


进程间通信的本质:让不同的进程,能看到同一份系统资源(系统通过某种方式提供的系统内存)

管道通信:

匿名管道 and 命名管道:底层的原理是基本一样的

匿名管道:

供具有血缘关系的进程,进行进程间通信(保证不同的进程,看到同一份资源)(常见于父子)

 

父子进程关闭不需要的文件描述符,来达到构建单向通信的信道的目的

这里有2个问题:

为什么需要关,那么曾经为什么要打开呢?

如果不打开读写,子进程拿到的文件打开方式必定和父进程一样,无法通信,同时更加灵活!

为什么要关闭?

一方面证明管道单向通信的特性,主要为了防止误操作

int pipe(int pipefd[2])  

输出型参数,通过调用pipe,拿到刚刚打开的管道文件的描述符

2个fd,对应于一个读,一个写

代码演示: 

#include<stdio.h>                                                                                                                                                                                                                                                             
  2 #include<unistd.h>
  3 #include<sys/wait.h>
  4 #include<stdlib.h>
  5 #include<string.h>
  6 int main()
  7 
  8   int pipe_fd[2] = 0;
  9   if(pipe(pipe_fd) < 0)
 10   
 11     perror("pipe");
 12     return 1;
 13   
 14 
 15   printf("%d,%d\\n",pipe_fd[0],pipe_fd[1]);
 16 
 17   pid_t id = fork();
 18   if(id < 0)
 19   
 20     perror("fork");
 21     return 2;
 22   
 23   else if(id==0)
 24   
 25     //child让子进程进行写入
 26     close(pipe_fd[0]);
 27 
 28 
 29     const char*msg = "我是子进程\\n";
 30     int count = 5;
 31     while(count)
 32     
 33       write(pipe_fd[1],msg,strlen(msg));//向管道当中写入的功能
 34       sleep(1);
 35       count--;
 36     
 37     close(pipe_fd[1]);
 38     exit(0);
 39   
 40   else
 41     //child让父进行读取
 42     close(pipe_fd[1]);
 43     char buffer[64];
 44     while(1)
 45     
 46       buffer[0] = 0;
 47       ssize_t size = read(pipe_fd[0],buffer,sizeof(buffer)-1);//管道中读取
 48       if(size > 0)
 49       
 50         buffer[size] = 0;
 51         printf("从子进程中来的:%s\\n",buffer);
 52       
 53       else if(size == 0)
 54       
 55         printf("管道文件关闭,子进程退出\\n");
 56         break;
 57       
 58       else
 59         break;
 60       
 61     
 62     int status = 0;
 63     if(waitpid(id,&status,0)>0)
 64     
 65       printf("子进程退出,等待成功\\n");
 66     
 67     close(pipe_fd[0]);
 68   
 69   return 0;
 70 

管道的特性: 

如果管道里面已经没有消息,父进程(读端)在干什么?

等待,在等管道内部有数据就绪

如果管道里面写端已经写满了,继续写入,还能写吗?

不能,等待管道内部有空闲空间(等父进程读走)

第一:管道自带同步机制

第二:管道是单向通信的

第三:管道是面向字节流的

第四:管道只能保证具有血缘关系的进程通信,常用于父子

第五:管道可以保证一定程度的数据读取的原子性

第六:进程退出,曾经打开的文件也会被关掉,管道也是文件,所以管道的生命周期随进程

验证部分特性: 

read端write端结果
不读write阻塞
不写read阻塞
不写 & 关闭read读取到0,文件结束!
不读 & 关闭write被OS发送的SIGPIPE杀掉

读取关闭,一直在写

毫无意义,一直在写,本质就是在浪费系统资源,写进程会立马被OS终止掉!(通过发送信号终止子进程)

管道大小

64KB(非原子性写入管道当中的单元大小)

4KB(原子性写入的)

命名管道:

理解命名管道的原理

1:先保证两个进程能看到同一份资源

普通文件,是需要将数据刷新到磁盘的,持久化存储

命令行代码实验:

命名管道实现的相关代码:

Client端:

#include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<unistd.h>
  6 #include<string.h>
  7 
  8 #define FIFO "./fifo"
  9 int main()
 10 
 11   int fd = open(FIFO,O_WRONLY);
 12   if(fd < 0)
 13   
 14     perror("open");
 15     return 2;
 16   
 17   char buffer[128];
 18   while(1)
 19   
 20     printf("Please Enter");
 21     fflush(stdout);                                                                                                                                                                         
 22     buffer[0] = 0;
 23     ssize_t s = read(0,buffer,sizeof(buffer));//从标准输入里读数据
 24     if(s > 0)
 25     
 26       buffer[s] = 0;
 27       write(fd,buffer,strlen(buffer));//写到管道文件
 28     
 29     else if(s == 0)
 30     
 31       printf("client quit\\n");
 32       break;
 33     
 34     else
 35       break;
 36     
 37   
 38   close(fd);
 39   return 0;
 40 

server端:

#include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<unistd.h>
  6 
  7 #define FIFO "./fifo"
  8 int main()
  9 
 10   int ret = mkfifo(FIFO,0644);
 11   if(ret < 0)
 12   
 13     perror("mkfifo");
 14     return 1;
 15   
 16   int fd = open(FIFO,O_RDONLY);
 17   if(fd < 0)
 18   
 19     perror("open");
 20     return 2;
 21   
 22   char buffer[128];                                                                                                                                                                         
 23   while(1)
 24   
 25     buffer[0] = 0;
 26     ssize_t s = read(fd,buffer,sizeof(buffer));
 27     if(s > 0)
 28     
 29       buffer[s] = 0;
 30       printf("client : %s\\n",buffer);
 31     
 32     else if(s == 0)
 33     
 34       printf("client quit\\n");
 35       break;
 36     
 37     else
 38       break;
 39     
 40   
 41   close(fd);
 42   return 0;
 43 
~

makefile:

client:client.c
  5     gcc -o $@ $^
  6 server:ser.c
  7     gcc -o $@ $^
  8 .PHONY:clean
  9 clean:
 10   rm -f client ser fifo              

运行结果:

以上是关于Linux进程间通信的主要内容,如果未能解决你的问题,请参考以下文章

Linux进程间通信

Linux进程间通信——管道

Linux 进程间通信-管道

Linux 进程间通信(IPC)

linux进程间通信

[ Linux ] 进程间通信介绍 管道