利用匿名管道实现父子进程间通信,要求
1.父进程发送字符串“hello child”给子进程;
2.子进程收到父进程发送的数据后,给父进程回复“hello farther”;
3.父子进程通信完毕,父进程依次打印子进程的退出状态以及子进程的pid。


源代码:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
        int fd1[2],fd2[2];
        pipe(fd1);
  pipe(fd2);
        int pid=fork();
        if(pid>0)
        {
  close (fd1[0]);
  close (fd2[1]);
  char str[25];
                write(fd1[1],"hello child!\n",25);
  read(fd2[0],str,25);
  printf("%s",str);  
  
  int status;
                int i=wait(&status);
                printf("pid:%d\t%d\n",i,WIFEXITED(status));
 
  exit(0);       
        }
        else if(pid==0)
        {
  close (fd1[1]);
  close (fd2[0]);
                char str[25];
                read(fd1[0],str,25);
                printf("%s",str);
  write(fd2[1],"hello father\n",25);
  }      
        return 0;
}

匿名管道:是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称pipe文件,是一个只存在于内存的特殊文件。
匿名管道特点:
匿名管道是半双工的,数据只能向一个方向流动;
一个进程将数据写入管道,另一进程从管道中读取数据;
写入的内容添加在管道缓冲区的末尾,每次都是从缓冲区头部读出数据;
数据读出后将从管道中移走,其它读进程都不能再读到这些数据。
双向通信的建立
需要建立起两个管道
使用限制
只能用于具有亲缘关系的进程之间
如父子进程或兄弟进程之间

1.匿名管道的建立
基本函数
int pipe(int fd[2]);
参数说明
fd[2]描述管道两端
fd[0]只能用于读,称为管道读端
fd[1]只能用于写,称为管道写端
若试图从写端读,或者向读端写都将导致错误发生
返回值
成功时返回0,失败时返回-1
说明
基本文件I/O函数都可用于管道
如close()、read()、write()等
低层系统调用
sys_pipe( )-->do_pipe()

2.匿名管道的读操作
进程调用read()系统调用
内核最终调用与该文件描述符相关的文件操作表中所找到的read()方法
在管道情形下,read方法将指向pipe_read()函数
该系统调用可能以两种方式阻塞当前进程
系统调用开始时管道缓冲区为空
管道缓冲区没有包含所请求的字节(n个字节),写进程在等待缓冲区的空间时曾经被置为睡眠

3.匿名管道的写操作
进程调用write()系统调用
内核最终调用pipe_write()函数
如果管道没有读进程,写进程发送SIGPIPE信号
管道缓冲区一有空闲区域,写进程将试图写入数据
如果读进程不读出管道缓冲区中的数据,那么写操作将一直阻塞

管道操作的基本流程:
1)使用pipe函数创建管道;
2)用fork函数创建一个子进程;
3)关闭父子进程中不需要的文件描述符,使用管道进行通信;
由于以上对管道的操作是比较规范,也比较常用。所以在ANSI C中将以上操作定义在两个标准库函数中,分别是popen和pclose函数。
       FILE *  popen(const char * command,      const char * type) ;
       int        pclose(FILE *      f p) ;
  参数command是一个在shell中可以运行的命令字符串的指针;
  参数type是一个字符指针,这个参数只有两种值,分别是r和w,分别对
应popen函数的返回值是一个读打开文件指针,还是写打开文件指针。
函数失败返回NULL,并设置出错变量errno。
pclose函数的参数fp是一个popen打开的文件描述符,函数失败时返回-1。

Logo

更多推荐