进程间通信方式

  • 普通文件
  • 管道(pipe)
  • 信号(signal)
  • 共享内存(shared memory)
  • socketpair
  • socket

普通文件

    普通文件可能是我们接触的最早的进程间通信的方式了,只是在刚接触时,并不知道或了解进程是什么。多个进程可以通过读写同一个文件达到通信的目的。

管道

    管道是以半双工(数据可以在一个信号载体的两个方向上传输,但是不能同时传输)机制来通信的,分为匿名管道可有名管道;匿名管道只能用于有亲缘关系的进程,有名管道能用于有亲缘关系和无亲缘关系的进程。

// 匿名管道,模拟全双工
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(argc, char* argv[])
{
     int fd_first[2], fd_second[2];
     if( !(!pipe(fd_first) && pipe(fd_second)) ){
         perror("pipe");
         return -1;
     }
     pid_t pid = fork();
     if(pit == 0){  // Child process
          close(fd_first[0]); close(fd_second[1]);
          char msg[128] = "Hi, Parant process ...";
          write(fd_first[1], msg, strlen(msg) + 1);
          memset(msg, 0, sizeof(msg));
          read(fd_second[0], msg, sizeof(msg));
          printf("Message from Parent: %s\n", msg);
     }else{
          close(fd_first[1]); close(fd_second[0]);
          char msg[128] = {0};
          read(fd_first[0], msg, sizeof(msg));
          printf("Message from Child: %s\n", msg);
          memset(msg, 0, sizeof(msg));
          strcpy(msg, "Hi, Child ...");
          write(fd_second[1], msg, strlen(msg) + 1);
          wait(NULL); 
     }
     return 0;
}

// 有名管道 ipc_fifo_write.c
#include <stdio.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
      
int main()  
{  
     int ret = mkfifo("filename.ff", 0755);  
     if(ret != 0){  
          perror("mkfifo");  
          exit(-1);  
     }  
  
     int fd = open("filename.ff", O_WRONLY);  
     if(fd == -1){  
          perror("open");  
          exit(-1);  
     }  
  
     char msg[128] = "Hello world!";  
     ret = write(fd, msg, strlen(msg) + 1);  // Write to fifo.  
     if(ret < 0){  
          perror("write");  
     }   
             
     close(fd);  
     return 0;  
}  


// ipc_fifo_read.c
int main()  
{  
     int fd = open("filename.ff", O_RDONLY);  
     if(fd == -1){  
          perror("open");  
          exit(-1);  
     }  
            
     char msg[128] = {0};  
     int ret = read(fd, msg, sizeof(msg));  
     if(ret > 0){  
          printf("Message from FIFO : %s\n", msg);  
     }  
     perror("read");  
     close(fd);  
     return 0;  
}

共享内存

    

// 匿名共享
      int main()  
      {  
          void* shm = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANOYMOUS, -1,0);  
          if(shm == MAP_FAILED){  
               perror("mmap");  
               return 0;  
          }   
            
          pid_t pid = fork();  
          if(pid == 0){  
               *(int*)shm = 100;  
          }else{  
               sleep(1);  
               printf("From parent : %d\n", *(int*)shm);    
               wait(NULL);  
          }  
          munmap(shm, 1024);  
          return 0;  
      } 
// 有名共享
      #include <sys/mman.h>  
      #include <sys/stat.h>  
      #include <fcntl.h>  
      #include <stdio.h>  
      #include <stdlib.h>  
      #include <fcntl.h>  
  
      int main()  
      {  
          int fd = shm_open("/test.shm", O_RDWR, 0755);  
          if(fd < 0){  
              fd = shm_open("/test.shm", O_RDWR | O_CREAT, 0755);  
              if(fd < 0){  
                  perror("shm_open");  
                  return -1;  
              }   
              ftruncate(fd, 4096);  
          }  
            
          char* shm = (char*)mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
          pid_t pid = fork();  
          if(pid == 0){  
              strcmp(shm, "Hello world\n");  
          }else{  
              sleep(1);  
              printf("From shared memory : %s\n", shm);  
              wait(NULL);  
          }  
          munmap(shm);  
          return 0;  
      }   

socketpair

      #include <stdio.h>  
      #include <stdlib.h>  
      #include <sys/socket.h>  
      #include <sys/types.h>  
      #include <unistd.h>  
  
      int main()  
     {  
           int fd[2];  
           int ret = socketpair(AF_UNIX, SOCK_STREAM, 0,fd);  
           if(ret != 0){  
                 perror("socketpair");  
                 return -1;  
           }  
             
           pid_t pid = fork();  
           if(pid == 0){             // Child process  
                 close(fd[1]);  
            
                 int val = 0;  
                 while(1){  
                       sleep(1);  
                       ++val;  
                          
                       write(fd[0], &val, sizeof(val));  
                       read(fd[0], &val, sizeof(val));  
                       printf("Child : %d\n", val);  
                 }  
           }else{                  // Parent process  
                  close(fd[0]);  
  
                  int val;  
                  while(1){  
                        read(fd[1], &val, sizeof(val));  
                        printf("Parent : %d\n", val);  
                        ++val;  
                        write(fd[1], &val, sizeof(val));  
                  }  
           }  
           return 0;  
    }