进程间通信之匿名管道

管道由pipe函数创建

#include<unistd.h>

int pipe(int filedes[2]);

调用pipe函数在内核中开辟一块缓冲区(就是管道)用于通信,filedes[0]指向管道的读端,filedes[1]指向管道的写端。pipe函数调用成功返回0,调用失败返回-1。

比如,父进程关闭读端,子进程关闭写端。代码如下:

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 _pipe_fd[2]={-1,-1};

9            if(pipe(_pipe_fd)<0)

10            {

11                   perror("pipe");

12                   exit(1);

13            }

14           pid_t _pid=fork();

15           if(_pid<0)

16           {

17                   perror("fork");

18                   exit(2);

19           }

20           else if(_pid==0)

21           {

22                   close(_pipe_fd[0]);

23                   int count=10;

24                   char buf[]="hello world";

25                   while(count--)

26                   {

27                           write(_pipe_fd[1],buf,strlen(buf));

28                           sleep(1);

29                   }

30                   exit(0);

31           }

32           else

33           {

34                   close(_pipe_fd[1]);

35                   char buf[1024];

36                   while(1)

37                   {

38                           memset(buf,‘\0‘,sizeof(buf));

39                           ssize_t _size=read(_pipe_fd[0],buf,sizeof(buf)-1);

40                           if(_size>0)

41                           {

42                                   buf[_size]=‘\0‘;

43                                   printf("%s\n",buf);

44                           }

45                   }

46           }

47   }

运行结果:

使用管道有限制:两个进程通过一个管道只能实现单向通信。

使用管道需要注意以下四种情况:

1.如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数为0),而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次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 _pipe_fd[2]={-1,-1};

9            if(pipe(_pipe_fd)<0)

10            {

11                   perror("pipe");

12                   exit(1);

13            }

14           pid_t _pid=fork();

15           if(_pid<0)

16           {

17                   perror("fork");

18                   exit(2);

19           }

20           else if(_pid==0)

21           {

22                   close(_pipe_fd[0]);

23                   int count=10;

24                   int i=0;

25                   char buf[]="hello world";

26                   while(count--)

27                   {

28                         if(i==5)

29                         {

30                                 printf("I want to sleep");

31                                 break;

32                         }

33                           write(_pipe_fd[1],buf,strlen(buf));

34                           sleep(1);

35                           i++;

36                   }

37                 close(_pipe_fd[1]);

38           }

39           else

40           {

41                   close(_pipe_fd[1]);

42                   char buf[1024];

43                   while(1)

44                   {

45                           memset(buf,‘\0‘,sizeof(buf));

46                           ssize_t _size=read(_pipe_fd[0],buf,sizeof(buf)-1);

47                           if(_size>0)

48                           {

49                                   buf[_size]=‘\0‘;

50                                   printf("%s\n",buf);

51                           }

52                   }

53           }

54   }

运行结果:

2.如果有指向管道写端的文件描述符没有关闭(管道写端的引用计数大于0);而管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,当管道中剩余的数据都被读取后,再次read会阻塞,只有管道中有数据可读了才读取数据并返回。

代码如下:

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 _pipe_fd[2]={-1,-1};

9            if(pipe(_pipe_fd)<0)

10            {

11                   perror("pipe");

12                   exit(1);

13            }

14           pid_t _pid=fork();

15           if(_pid<0)

16           {

17                   perror("fork");

18                   exit(2);

19           }

20           else if(_pid==0)

21           {

22                   close(_pipe_fd[0]);

23                   int count=10;

24                   int i=0;

25                   char buf[]="hello world";

26                   while(count--)

27                   {

28                           if(i==5)

29                           {

30                                 printf("I am child\n");

31                                 sleep(10);

32                           }

33                           write(_pipe_fd[1],buf,strlen(buf));

34                           sleep(1);

35                           i++;

36                   }

37                   exit(0);

38                   close(_pipe_fd[1]);

39           }

40           else

41           {

42                   close(_pipe_fd[1]);

43                   char buf[1024];

44                   while(1)

45                   {

46                           memset(buf,‘\0‘,sizeof(buf));

47                           ssize_t _size=read(_pipe_fd[0],buf,sizeof(buf)-1);

48                           if(_size>0)

49                           {

50                                   buf[_size]=‘\0‘;

51                                   printf("%s\n",buf);

52                           }

运行结果:

3.如果指向所有管道读端的文件描述符都关闭了(管道读端的文件描述符为0),当有进程向管道的写端写数据时,该进程会收到信号SIGPIPE,通常会导致进程异常终止。

代码如下:

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 _pipe_fd[2]={-1,-1};

9            if(pipe(_pipe_fd)<0)

10            {

11                   perror("pipe");

12                   exit(1);

13            }

14           pid_t _pid=fork();

15           if(_pid<0)

16           {

17                   perror("fork");

18                   exit(2);

19           }

20           else if(_pid==0)

21           {

22                   close(_pipe_fd[0]);

23                   int count=10;

24                   char buf[]="hello world";

25                   while(count--)

26                   {

27                           write(_pipe_fd[1],buf,strlen(buf));

28                           sleep(1);

29                   }

30                   close(_pipe_fd[1]);

31           }

32           else

33           {

34                   close(_pipe_fd[1]);

35                   char buf[1024];

36                   int j=5;

37                   while(j--)

38                   {

39                           if(j==3)

40                           {

41                                 close(_pipe_fd[0]);

42                           }

43                           memset(buf,‘\0‘,sizeof(buf));

44                           ssize_t _size=read(_pipe_fd[0],buf,sizeof(buf)-1);

45                           if(_size>0)

46                           {

47                                   buf[_size]=‘\0‘;

48                                   printf("%s\n",buf);

49                           }

50                   }

51                 int status=0;

52                 pid_t _id=waitpid(_pid,&status,0);

53                 printf("waitpid:%d,status:%d\n",_id,status&0xff);

54           }

55         return 0;

56   }

运行结果:

4.如果有指向管道读端的文件描述符没有关闭(管道写端的引用计数大于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 _pipe_fd[2]={-1,-1};

9            if(pipe(_pipe_fd)<0)

10            {

11                   perror("pipe");

12                   exit(1);

13            }

14           pid_t _pid=fork();

15           if(_pid<0)

16           {

17                   perror("fork");

18                   exit(2);

19           }

20           else if(_pid==0)

21           {

22                   close(_pipe_fd[0]);

23                   int count=10;

24                   char buf[]="hello world";

25                   while(count--)

26                   {

27                           write(_pipe_fd[1],buf,strlen(buf));

28                           sleep(1);

29                   }

30                  close(_pipe_fd[0]);

31           }

32           else

33           {

34                 close(_pipe_fd[1]);

35                 int status=0;

36                 pid_t id=waitpid(_pid,&status,0);

37                 if(id==_pid)

38                 {

39                         printf("id:%d,status:%d",id,status);

40                 }

41

42           }

43 }

运行结果:

总结:匿名管道有以下特点:

(1)匿名管道提供的通信是单向的;

(2)匿名管道通信用于有关系的进程间,通常用于父子进程之间(命名管道将针对于这一问题进行解决);

(3)匿名管道能够实现进程间的同步与互斥;

(4)匿名管道的生命周期随进程。

时间: 2024-12-22 12:02:24

进程间通信之匿名管道的相关文章

进程间通信IPC—匿名管道(pipe)和命名管道(fifo)

管道内部如何实现-大小,组织方式,环形队列? 一.进程间通信有多种方式,本文主要讲解对管道的理解.管道分为匿名管道和命名管道. (1)管道( pipe ):又称匿名管道.是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. (2)命名管道 (named pipe或FIFO) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信. 二.管道 1. 管道的特点: (1)管道是半双工的,数据只能向一个方向流动:双方通信时,需要

Linux进程间通信 -- 使用匿名管道

在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据. 一.什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号“|"来使用管道,但是管理的真正定义是什么呢?管道是一个进程连接数据流到另一个进程的通道,它通常是用作把一个进程的输出通过管道连接到另一个进程的输入. 举个例子,在shell中输入命令:ls -l

Python进程间通信之匿名管道

匿名管道 管道是一个单向通道,有点类似共享内存缓存.管道有两端,包括输入端和输出端.对于一个进程的而言,它只能看到管道一端,即要么是输入端要么是输出端. os.pipe()返回2个文件描述符(r, w),表示可读的和可写的.示例代码如下: #!/usr/bin/python import time import os def child(wpipe): print('hello from child', os.getpid()) while True: msg = 'how are you\n'

在Linux下的进程间通信之匿名管道

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到.所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2 在从内核缓冲区把数据读走. 管道是一种最基本的IPC机制,由pipe函数创建: 调用pippe函数时在内核中开辟一块缓冲去(称为管道)用于通信,它有一个读端,一个写端,然后通过fileds参数传出给用户程序两个文件描述符,fileds[0]指向管道的读端,fileds[1]指向管道的写端,所以管道在用户程序看起来

进程间通信_02匿名管道

相关介绍                      分配一块独立于进程的内存,对内存的操作方式和对文件的操作方式类似.有如下特点: 1  只能用于父子进程之间. 2  管道的大小是有限制(一个页面的大小,4K字节). 3  数据是单向流动的. 4  传送的是无格式字节流,需要双方事先确定好长度 格式等. 操作函数 1 创建一个管道 #include <unistd.h> int pipe( int fildes[2] ); //出参,用于管道读写端的文件描述符: 返回值:0(成功)/-1(失败

Linux进程间通信 -- 使用命名管道

在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进程之间交换数据带来了不方便.这里将会介绍进程的另一种通信方式——命名管道,来解决不相关进程间的通信问题. 一.什么是命名管道 命名管道也被称为FIFO文件,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和之前所讲的没有名字的管道(匿名管道)类似. 由于Linux中所有

IPC——匿名管道

Linux进程间通信——使用匿名管道 在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据. 一.什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号“|"来使用管道,但是管理的真正定义是什么呢?管道是一个进程连接数据流到另一个进程的通道,它通常是用作把一个进程的输出通过管道连接到另一个进程的输入. 举个例子

进程间通信(1)---匿名管道与命名管道

管道是进程间通信一种基本的的一种方式,管道又分为两种,匿名管道和命名管道,先说匿名管道 匿名管道(pipe) #include <unistd.h> int pipe(int filedes[2]); 调用pipe时会在内核中开辟一个缓冲区,使用时fileds[0]为输出端,fileds[1]为写入端口,调用成功时返回0,失败时返回-1: pipe的特点: 1:它只能在有血缘关系的进程间进行通信. 2:它只能进行单项通信,一个进程读,另一个只能写. 3:它是一种流式服务. 4:它的生命周期跟随

Linux - 进程间通信 - 匿名管道

一.概念:进程间通信( IPC,InterProcess Communication) 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进城之间要交换数据必须通过内核, 在内核中 开辟一块缓冲区进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内接提供的这种机制成为进程间 通信(IPC,InterProcess Communication). 二.管道 管道分为匿名管道和命名管道,这里我们只讲匿名管道,命名管道的实现将在下一篇文章中分享.