溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

發(fā)布時間:2020-08-18 09:52:10 來源:網(wǎng)絡(luò) 閱讀:2564 作者:小止1995 欄目:編程語言

通信:因?yàn)檫M(jìn)程有強(qiáng)大獨(dú)立性,當(dāng)想把自己數(shù)據(jù)交給另一個進(jìn)程,需要通信。

通信本質(zhì):讓不同進(jìn)程看到相同資源。

實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

  1. 匿名管道:管道:通過某種機(jī)制傳遞資源(數(shù)據(jù)),匿名管道只適用于有血緣關(guān)系的進(jìn)程,一般用于父,子進(jìn)程通信。

    a.創(chuàng)建管道

    b.創(chuàng)建子進(jìn)程

    c.父,子進(jìn)程關(guān)閉自己不需要的文件描述符

    注意:匿名管道提供單向通信,父讀子寫或父寫子讀,若要實(shí)現(xiàn)雙向通信,可再創(chuàng)建一個管道。

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{
    int _pipefd[2]={-1,-1};
    int ret=pipe(_pipefd);
    if(ret==-1)
    {
        perror("pipe");
        return 2;
    }
    pid_t id=fork();
    if(id<0)
    {
        perror("fork");
        return 2;
    }
    else if(id==0)
     {
        close(_pipefd[0]);
        char buf[]="hello world";
        int count=5;
        while(count--)
        {
            write(_pipefd[1],buf,strlen(buf));
            sleep(1);
        }
    }
    else
     {  
       close(_pipefd[1]);
       char buf[1024]={0};
       while(1)
        {
          memset(buf,'\0',sizeof(buf));
          ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
          if(_size>0)
          {
               buf[_size]='\0';
               printf("buf:%s\n",buf);
          }    
        }
    }
    return 0; 
}

運(yùn)行結(jié)果:實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

使用管道需注意以下四種情況:

1.如果所有指向管道寫端的文件描述符都關(guān)閉了,仍然有進(jìn)程從管道的讀端讀數(shù)據(jù),那么管道中剩余的數(shù)據(jù)都被讀取后,再次read會返回0,就像讀到文件末尾一樣。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<unistd.h>
  4 #include<sys/types.h>
  5 #include<stdlib.h>
  6 int main()
  7 {
  8     int _pipefd[2]={-1,-1};
  9     int ret=pipe(_pipefd);
 10     if(ret==-1)
 11     {
 12         perror("pipe");
 13         return 2;
 14     }
 15
 16     pid_t id=fork();
 17     if(id<0)
 18     {
 19         perror("fork");
 20         return 2;
 21     }
 22     else if(id==0)
 23      {
 24         close(_pipefd[0]);
 25         char buf[]="hello world";
 26         int count=5;
 27         int i=0;
 28         while(count--)
 29         {
 30             if(i==3)
 31             {
 32                 printf("I want sleep\n");
 33                 break;
 34             }
 35             write(_pipefd[1],buf,strlen(buf));
 36             sleep(1);
 37             i++;
 38         }
 39         close(_pipefd[0]);
 40     }
 41     else
 42     {
 43         close(_pipefd[1]);
 44         char buf[1024]={0};
 46         while(1)
 47         {
 48             memset(buf,'\0',sizeof(buf));
 49             ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
 50             if(_size>0)
 51             {
 52                   buf[_size]='\0';
 53                 printf("buf:%s\n",buf);
 54             }
 55         }
 56     }
 57     return 0;
 58 }

運(yùn)行結(jié)果:實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

2.如果有指向管道寫端的文件描述符沒關(guān)閉,持有管道寫端的進(jìn)程也沒有向管道中寫數(shù)據(jù),這時有進(jìn)程從管道讀端讀數(shù)據(jù),那么管道中剩余的數(shù)據(jù)都被讀取后,再次read會阻塞,直到管道中有數(shù)據(jù)可讀了才讀取數(shù)據(jù)并返回。

1 #include<stdio.h>
  2 #include<sys/wait.h>
  3 #include<string.h>
  4 #include<unistd.h>
  5 #include<sys/types.h>
  6 #include<stdlib.h>
  7 int main()
  8 {
  9     int _pipefd[2]={-1,-1};
 10     int ret=pipe(_pipefd);
 11     if(ret==-1)
 12     {
 13         perror("pipe");
 14         return 2;
 15     }
 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         close(_pipefd[0]);
 26         char buf[]="hello world";
 27         int count=5;
 28         int i=0;
 29         while(count--)
 30         {
 31              if(i==3)
 32              {
 33                   printf("I want sleep\n");
 34                   sleep(10);
 35              }
 36              write(_pipefd[1],buf,strlen(buf));
 37              sleep(1);
 38              i++;
 39         }
 40         close(_pipefd[0]);
 41     }
 42     else
 43     {
 44         close(_pipefd[1]);
 45         char buf[1024]={0};
 46         while(1)
 47         {
 48             memset(buf,'\0',sizeof(buf));
 49             ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
 50             if(_size>0)
 51             {
 52                 buf[_size]='\0';
 53                 printf("buf:%s\n",buf);
 54             }
 55         }
 56     }
 57     return 0;
 58 }

運(yùn)行結(jié)果:

實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

3.如果所有指向管道讀端的文件描述符都關(guān)閉了,這時有進(jìn)程向管道的寫端write,那么該進(jìn)程會收到信號SIGPIPE,通常會導(dǎo)致進(jìn)程異常終止。

  1 #include<stdio.h>
  2 #include<sys/wait.h>
  3 #include<string.h>
  4 #include<unistd.h>
  5 #include<sys/types.h>
  6 #include<stdlib.h>
  7 int main()
  8 {
  9     int _pipefd[2]={-1,-1};
 10     int ret=pipe(_pipefd);
 11     if(ret==-1)
 12     {
 13         perror("pipe");
 14         return 2;
 15     }
 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         close(_pipefd[0]);
 26         char buf[]="hello world";
 27         int count=5;
 28         while(count--)
 29         {
 30              write(_pipefd[1],buf,strlen(buf));
 31              sleep(1);
 32         }
 33         close(_pipefd[0]);
 34     }
 35     else
 36     {
 37         close(_pipefd[1]);
 38         char buf[1024]={0};
 39         int i=5;
 40         while(i--)
 41         {
 42             if(i==3)
 43             {
 44                 close(_pipefd[0]);
 45             }
 46             memset(buf,'\0',sizeof(buf));
 47             ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
 48             if(_size>0)
 49             {
 50                 buf[_size]='\0';
 51                 printf("buf:%s\n",buf);
 52             }
 53         }
 54         int status=0;
 55         pid_t _pid=waitpid(id,&status,0);
 56         printf("waitpid: %d,return status:%d\n",id,status&0xff);
 57     }
 58     //printf("%d ,%d \n",_pipefd[0],_pipefd[1]);
 59     return 0;
 60 }

運(yùn)行結(jié)果:

實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道


4.如果有指向管道讀端的文件描述符沒關(guān)閉,持有管道讀端的進(jìn)程也沒有從管道中讀數(shù)據(jù),這時有進(jìn)程向管道寫端寫數(shù)據(jù),那么在管道被寫滿時再次write會阻塞,直到管道中有空位置了才寫入數(shù)據(jù)并返回。 

  1 #include<stdio.h>
  2 #include<sys/wait.h>
  3 #include<string.h>
  4 #include<unistd.h>
  5 #include<sys/types.h>
  6 #include<stdlib.h>
  7 int main()
  8 {
  9     int _pipefd[2]={-1,-1};
 10     int ret=pipe(_pipefd);
 11     if(ret==-1)
 12     {
 13         perror("pipe");
 14         return 2;
 15     }
 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         close(_pipefd[0]);
 26         char buf[]="hello world";
 27         int count=5;
 28         while(count--)
 29         {
 30              write(_pipefd[1],buf,strlen(buf));
 31              sleep(1);
 32         }
 33         close(_pipefd[0]);
 34     }
 35     else
 36     {
 37         close(_pipefd[1]);
 38         int status=0;
 39         pid_t wait=waitpid(id,&status,0);
 40         if(wait==id)
 41            printf("wait:%d,status:%d\n",wait,status);
 42     }
 43     return 0;
 44 }

總結(jié)匿名管道特點(diǎn):

  1. 單向通信,適用于有血緣關(guān)系的進(jìn)程通信。

  2. 管道提供流式服務(wù)(數(shù)據(jù)按序,不規(guī)定一次讀多少)

  3. 管道內(nèi)部有保證數(shù)據(jù)讀完(完整性)。

  4. 進(jìn)程間同步

通過路徑看到共同資源

  1. 在shell下交互的建立

  2. 調(diào)用函數(shù)

//client:
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<stdlib.h>
  6 #include<string.h>
  7 #include<fcntl.h>
  8 int main()
  9 {
 10     umask(0);
 11     int fd=mkfifo("./.tmp",S_IFIFO|0666);
 12     if(fd<0)
 13     {
 14         perror("mkfifo");
 15         exit(1);
 16     }
 17     int _fd=open("./.tmp",O_WRONLY);
 18     if(_fd<0)
 19     {
 20         perror("mkfifo");
 21         exit(1);
 22     }
 23     while(1)
 24     {
 25     char buf[1024];
 26     fflush(stdout);
 27     memset(buf,'\0',sizeof(buf));
 28     printf("client:");
 29     size_t size=read(0,buf,sizeof(buf)-1);
 30     buf[size]='\0';
 31     write(_fd,buf,strlen(buf));
 32     }
 33     return 0;
 34 }
//server:
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<unistd.h>
  7 #include<stdlib.h>
  8 int main()
  9 {
 10     int _fd=open("./.tmp",O_RDONLY);
 11     if(_fd<0)
 12     {
 13         perror("open");
 14         exit(1);
 15     }
 16     char buf[1024];
 17     while(1)
 18     {
 19         memset(buf,'\0',sizeof(buf));
 20         ssize_t _size=read(_fd,buf,sizeof(buf)-1);
 21         if(_size>0)
 22         {
 23             buf[_size]='\0';
 24             printf("server:%s",buf);
 25         }
 26         else
 27         {
 28             printf("read error\n");
 29             break;
 30         }
 31     }
 32     close(_fd);
 33     return 0;
 34 }
//Makefile編寫:
 .PHONY:all
  2 all:client server
  3
  4 client:client.c
  5     gcc -o $@ $^
  6 server:server.c
  7     gcc -o $@ $^
  8 .PHONY:clean
  9 clean:
 10     rm -f client server .tmp

結(jié)果驗(yàn)證:打開兩個終端,不同進(jìn)程可以通信。

實(shí)現(xiàn)進(jìn)程間通信:匿名管道和命名管道

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI