进程间通信(一)

(一)管道

 

(1)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;

(2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

(3)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据

fsd[0]:读端描述符

fsd[1] :写端描述符

 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define MAX 1024

main()
{
 char buffer[1024];
 int fds[2];
 pid_t pid;
 pipe(fds);
 pid = fork();
 if(pid < 0)
 {
  printf("fork error");
  exit(0);
 }
 else if(pid > 0)
 {
  close(fds[0]);
  write(fds[1], "i love my mother!", 100);
 }
 else
 {
  close(fds[1]);
  read(fds[0], buffer, 100);
  printf("%s/n", buffer);
 }

输出:

i love my mother!

 

管道的读规则:

 

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define MAX 1024

main()
{
 int num, shu;
 int fds[2];
 char a[100];
 char b[100];
 pid_t pid;
 
 memset(a, 0, 10);
 memset(b, 0, 10);
 if(pipe(fds))
 {
  printf("creat error!");
  exit(0);
 }
 pid = fork();
 if(pid < 0)
 {
  printf("fork error!");
  exit(0);
 }
 else if(pid == 0)
 {
  close(fds[1]);
  sleep(2);
  num = read(fds[0], a, 100);
  shu = atoi(a);
  printf("num = %d/nshu = %d/n", num, shu);
 }
 else if(pid > 0)
 {
  strcpy(b, "1234");
  close(fds[0]);
  if(write(fds[1], b, 100) == -1)
  {
   printf("parent write over!");
   exit(0);
  }
  close(fds[1]);
  sleep(5);
 }
}

output:
num = 100;
shu = 1234;

结论:管道写端关闭后,写入的数据将一直存在,直到读出为止.

向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。

管道的写规则

 

1.写端对读端存在的依赖性

例子:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define MAX 1024

main()
{
 int num, shu;
 int fds[2];
 char a[100];
 char b[100];
 pid_t pid;
 
 memset(a, 0, 10);
 memset(b, 0, 10);
 if(pipe(fds))
 {
  printf("creat error!");
  exit(0);
 }
 pid = fork();
 if(pid < 0)
 {
  printf("fork error!");
  exit(0);
 }
 else if(pid == 0)
 {
  close(fds[1]);
  close(fds[0]);
  sleep(3);
  num = read(fds[0], a, 100);
  shu = atoi(a);
  printf("num = %d/nshu = %d/n", num, shu);
 }
 else if(pid > 0)
 {
  sleep(1);
  strcpy(b, "1234");
  printf("%s/n", b);
  close(fds[0]);
  if(write(fds[1], b, 100) == -1)
  {
   printf("parent write over!");
   exit(0);
  }
  printf("%s/n", b);
//  sleep(5);
 }
}

output:
1234
num = -1
shu = 0

最后一个输出没有用了!

只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。

 

 

kill -l

 

pipe的不足:

1 没有名字

2 是单方向的

3 只能用于具有亲缘关系的进程间

4 管道的缓冲区是有限的  (管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小)

 

有名管道

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值