center进程间通信center

Posted *insist

tags:

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

进程间通信

文章目录

1.1进程间通信的概念

进程间通信就是进程之间进行信息的交换和传播

很重要的一句话:进程间通信的本质是让不同的进程看到同一根资源

1.2进程间通信的目的

  • 数据传输:一个进程需要将自己的数据发生给其他的进程
  • 资源共享:多个进程之间共用相同的资源
  • 通知事件:一个进程需要向拎一个进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)
  • 进程控制:有些进程希望完全控制另一个进程的执行(如debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变

1.3进程间通信的方式

  • 管道(本文主讲)
    • 匿名管道pipe
    • 命名管道
  • System V进程间通信(本文不涉及)
    • System V消息队列
    • System V共享内存
    • System V信号量
  • POSIX进程间通信(本文不涉及)
    • 消息队列
    • 共享内存
    • 信号量
    • 互斥量
    • 条件变量
    • 读写锁

2.1管道的概念

管道是一种古老的进程间通信的形式

  • 通常把一个进程连接到另一个进程的一个数据流称为一个“管道”

2.2匿名管道的介绍

匿名管道就是没有名字的管道,由函数pipe(int fd[2]) 创建,常用于具有亲缘关系的进程间进行通信,作为两个进程共享的资源,从而实现两个进程间的信息交换达到通信的目的。

2.2.1管道的5种特征4种情况

5种特征:

  • 1.管道内部已经自动提供了同步与互斥机制(读和写只能一个进行另一个等待,不能同时进行)

  • 2.如果打开文件的进程退出了,文件也会被释放掉(所有打开了某一文件的进程全部退出了,该文件的资源才会彻底释放掉)

  • 3.管道是提供流式服务的(本文只是提及,知道有这么个东西即可,后续的博客应该会讲)

  • 4.管道是半双工通信的(管道只能是单向通信的,例如父进程在进行写入数据到匿名管道,那么子进程就不能进行读取管道信息,必须等父进程写完了才可以进行读操作,也就是父子进程只能是其中一个对管道进行读或写操作,不能父子进程同时对管道进行读或者写操作!!!)

  • 5.匿名管道适合具有血缘关系的进程进行进程间通信,常用于父子

4种情况:

  • 1.(子或父)不write,(父或子)一直read,read阻塞
  • 2.(子或父) 不read ,(父或子)一直write,write阻塞
  • 3.write写完后关闭,read返回值为0
  • read关闭,一直写,写方会被操作系统杀掉,写入无意义

2.3管道读写的规则说明

(fd_arrray[3] fd_array[4] 不理解的第三张图有解释)

通过pipe(int fd[2])创建了管道后,再通过fork()创建子进程

错误读写:

正确读写:

父进程读,子进程写的相关代码(本文主要代码,举例也是这在这段代码的基础上变换来的):

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

int main()

  int fd[2];
  if(pipe(fd)<0)
  
    //创建管道
    perror("pipe!");//这个函数自带换行
    return 1;
  
  //printf("fd[0]\\n",fd[0]);
  //printf("fd[1]\\n",fd1]);
  
  //创建子进程
   
  pid_t id = fork();
  if(id==0)
  
    //child
    //子进程要做的是向管道里写数据 要把读端关闭 最后写完了再把写端关闭
    close(fd[0]);
    int count=10;
   const char* str="hello father i am your child!\\n";

    while(count)
    
      write(fd[1],str,strlen(str));
    //  printf("%s",str);
      count--;
      sleep(1);
    
    close(fd[1]);
    exit(1);
    
  
  else if(id>0)
  
    //father
    close(fd[1]);//父进程关闭写端,只进行读
    char buff[64];
    while(1)
    
      int ret=read(fd[0],buff,sizeof(buff));
      if(ret>0)
      
        buff[ret]='\\0';
        printf("child send to father's message is:%s\\n",buff);
     //   close(fd[0]);
      //  break;
      //这里不能直接就break 不然就是只读了一次 这里写了10次要一直读 直到读到了文件结尾才停止 才能读完
      
      else if(ret==0)
      
        printf("read file of end!\\n");
        break;
      
      else 
      
        perror("read");
        break;
      

    
  
  else
  
    //error
    perror("fork!");
    return 1;
  

    int status=0;
    int ret=waitpid(id,&status,0);//阻塞式等待
    if(ret>0)
    
      printf("child is quit! single is:%d",status&0x7F);

    

  return 0;


4种情况的分析:

第一种:(子或父)不write,(父或子)一直read,read阻塞

代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<string.h>
int main()

  int fd[2];
 int ret = pipe(fd);
 if(ret<0)
 
   perror("pipe");
   return -1;
 

 pid_t id=fork();//创建子进程
 if(id==0)
 
   //child
  close(fd[0]);//子进程关闭读端 使得其只能往管道中进行写入
  const char* str="i\\n";

  int count=5;
  while(count)
  
  if(count>=2)//count 大于等于2就写 否则就休眠
    
     write(fd[1],str,strlen(str));
     count--;
     sleep(1);
    
   else
      sleep(1000);//子进程写两次就不写了 进行休眠 但是父进程一直在读 这样就会形成读堵塞
    
  
  //一直写 当不再打印count时说明管道的缓冲区写满了,此时的count就是管道的容量
 

 else if(id>0)
 
   //father
   close(fd[1]);//关闭写端
  // sleep(1000);
   char arr[1000];
   while(1)
   
     int ret=read(fd[0],arr,sizeof(arr));
      if(ret>0)//读到了内容
      
        arr[ret]='\\0';
        printf("%s",arr);
      
      else if(ret==0)
      
        //读到了文件结尾
        printf("read end of file!\\n");
        break;
      
      else
      
        //read error
       // perror("read");
       printf("read error!\\n");
        break;
      
 
 
 else
 
   //error
  perror("fork!");
 
  int status=0;
  int s=waitpid(id,&status,0);//阻塞式等待
  if(s>0)
  
  printf("child quit!\\n");
  
  else
  
    printf("wait error!");
  
  printf("quit singal is:%d\\n",ret&0x7F);
  return 0;


第二种:(子或父) 不read ,(父或子)一直write,write阻塞

代码:

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


int main()


  int fd[2];
 int ret = pipe(fd);
 if(ret<0)
 
   perror("pipe");
   return -1;
 

 pid_t id=fork();//创建子进程
 if(id==0)
 
   //child
  close(fd[0]);//子进程关闭读端 使得其只能往管道中进行写入
  const char* str="i";//每次写一个字节
  int count=0;
  while(1)
      
  write(fd[1],str,strlen(str));
  count++;
  printf("%d\\n",count);//写一次打印一次count 
  
  //一直写 当不再打印count时说明管道的缓冲区写满了,此时的count就是管道的容量
 

 else if(id>0)
 
   //father
   close(fd[1]);//关闭写端
   sleep(1000);//直接让父进程休眠,就不会读取管道里的数据,让子进程一直往里写就行了
   char arr[1000];
   while(1)
   
    
     int ret=read(fd[1],arr,sizeof(arr));
     while(1)
     
      if(ret>0)//读到了内容
      
        arr[ret]='\\0';
        printf("%s",arr);
      
      else if(ret==0)
      
        //读到了文件结尾
        printf("read end of file!\\n");
        break;
      
      else
      
        //read error
        perror("read");
        break;
      
     
   
 
 else
 
   //error
  perror("fork!");
 
    //等待子进程退出
  int status=0;
  int s=waitpid(id,&status,0);//阻塞式等待
  if(s>0)
  

  printf("child quit!\\n");
  
  else
  
    printf("wait error!");
    
  
  
  printf("quit singal is:%d\\n",ret&0x7F);
  return 0;



运行结果-> 不再打印count 说明write阻塞了 测得管道缓冲区大小为65536个字节

结合文档 本机是3.几的版本 所以是65536个字节 得到证实

第三种:.write写完后关闭,read返回值为0

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

int main()

  int fd[2];
 int ret = pipe(fd);
 if(ret<0)
 
   perror("pipe");
   return -1;
 

 pid_t id=fork();//创建子进程
 if(id==0)
 
   //child
  close(fd[0]);//子进程关闭读端 使得其只能往管道中进行写入
  const char* str="i\\n";//每次写一个字节

  int count=5;
  while(count)
  
     write(fd[1],str,strlen(str));
     count--;
     sleep(1);
  
	//重点
  close(fd[1]);//写完关闭 写端 父进程读的时候就会读到文件结尾 返回值为0
  exit(0);//子进程写完退出
 

 else if(id>0)
 
   //father
   close(fd[1]);//关闭写端
  // sleep(1000);
   char arr[1000];
   while(1)
   
     int ret=read(fd[0],arr,sizeof(arr));
      if(ret>0)//读到了内容
      
        arr[ret]='\\0';
        printf("%s",arr);
      
      else if(ret==0)
      
        //读到了文件结尾
        printf("read end of file!\\n");
        break;
      
      else
      
        //read error
       // perror("read");
       printf("read error!\\n");
        break;
      
   
   
  int status=0;
  int s=waitpid(id,&status,0);//阻塞式等待
  if(s>=0)
  
   printf("child quit!\\n");
  
  else
  
    printf("wait error! s:%d\\n",s);
    
  
  
  printf("quit singal is:%d\\n",status&0x7F);

  return 0;
 
 else
 
   //error
  perror("fork!");
 

  return 0;


运行结果:写端写完关闭 读端再读 读到文件结尾 read返回值为0

第四种:read关闭,一直写,写方会被操作系统杀掉,写入无意义

代码:

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


int main()


  int fd[2];
 int ret = pipe(fd);
 if(ret<0)
 
   perror("pipe");
   return -1;
 

 pid_t id=fork();//创建子进程
 if(id==0)
 
   //child
  close(fd[0]);//子进程关闭读端 使得其只能往管道中进行写入
  const char* str="i\\n";//每次写一个字节

  while(1)
  
     write(fd[1],str,strlen(str));
     sleep(1);
  
  

  close(fd[1]);//写完关闭 写端 父进程读的时候就会读到文件结尾 返回值为0
  exit(0);
 

 else if(id>0)
 
   //father
   close(fd[1]);//关闭写端
   close(fd[0]);//父进程直接关闭读端 不读取管道信息 子进程还在一直写 没有意义 操作系统会将其杀掉
  // sleep(1000);
   char arr[1000];
   while(1)
   
     int ret=read(fd[0],arr,sizeof(arr));
      if(ret>0)//读到了内容
      
        arr[ret]='\\0';
        printf("%s",arr);
      
      else if(ret==0)
      
        //读到了文件结尾
        printf("read end of file!\\n");
        break;
      
      else
      
        //read error
       // perror("read");
       printf("read error!\\n")ActiveMQ在Center OS7上的安装以及在windows上访问activemq

进程间的几种通信方式

Python字符串capitalize center 方法

[Linux]进程间通信

[Linux]进程间通信

linux系统进程间通信方式:管道