普通管道:
1.半双工
2.具有公共祖先,比如:一个进程pipe创建一个管道,然后fork创建一个子进程,那么,父子进程就公用了该管道
#include <unistd.h>
int pipe(int fd[2]);
其中fd[0]为读而打开,fd[1]为写而打开
当父进程fork出子进程以后,父子进程就各自都拥有自己的fd[0]和fd[1]
比如:如果要实现从父进程到子进程的管道,则父进程关闭管道的读(fd[0]),子进程关闭管道的写(fd[1]);看代码:
#include<stdlib.h>
#include< string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>

#define MAXLINE 50

main(void)
{
        int         n;
        int         fd[2];
        pid_t     pid;
        char        line[MAXLINE];

         if (pipe(fd) < 0)  printf( "pipe error");
         if ((pid = fork()) < 0)  printf( "fork error"); 
         else if (pid > 0)
        {             /* parent */
                close(fd[0]);
                sleep(10);
                write(fd[1], "hello world\n", 12);
        }
         else
        {             /* child */
                close(fd[1]);
                n = read(fd[0], line, MAXLINE);
                printf( "n=%d,line:%s",n,line);
        }
         exit(0);
}
程序说明:
1. 其中sleep(10)是为了证明子进程中的read管道是阻塞的。在管道中有这么一种说法:当读一个空管道时,在有数据写入这个管道之前,这个读函数将一直阻塞,当写一个满管道时候,在有数据从这个管道读走之前,这个写函数将一直阻塞。
2. 当多个进程同时写管道时(当然普通管道大家一般都不这么做,但在FIFO管道的时候确实如此),常量PIPE_BUF规定了内核中管道缓冲区的大小,如果对管道写的字节数小于PIPE_BUF,那么这一次写就不会被打断,也就是说,如果大于PIPE_BUF,那么这一次写,可能被其他进程的写穿插进来,执行了其它程序的写,然后再继续写。
程序执行结果是:
(等待10s)
n=12,line:hello world
应用举例1
在我的《父子进程---竞争》一文中,有说到关于TELL_WAIT,TELL_PARENT,TELL_CHILD,WAIT_PARENT,WAIT_CHILD
其实就是管道的实现:
#include "apue.h"

static int    pfd1[2], pfd2[2];

void TELL_WAIT(void)
{
         if (pipe(pfd1) < 0 || pipe(pfd2) < 0)  err_sys( "pipe error");
}

void TELL_PARENT(pid_t pid)
{
         if (write(pfd2[1], "c", 1) != 1)
                err_sys( "write error");
}

void WAIT_PARENT(void)
{
        char        c;
         if (read(pfd1[0], &c, 1) != 1) err_sys( "read error");
         if (c != 'p') err_quit( "WAIT_PARENT: incorrect data");
}

void TELL_CHILD(pid_t pid)
{
         if (write(pfd1[1], "p", 1) != 1)  err_sys( "write error");
}

void WAIT_CHILD(void)
{
        char  c;
         if (read(pfd2[0], &c, 1) != 1) err_sys( "read error");
         if (c != 'c') err_quit( "WAIT_CHILD: incorrect data");
}
程序分析:
1.首先在父进程中创立了两个管道,那父进程就有两个读,两个写,接着,子进程   复制父进程,也有两个读,两个写。
  为什么不用一个管道就实现呢?因为这里假设管道是半双工的(保证可移植       性),并且如果只有一个管道,那势必一个进程在读的时候还要写,比如读在阻   塞中,要写,必须另建线程,就增加了程序远的负担,还不如创建两个管道
2.为什么管道1和管道2都有一部分不必要的读写没关掉?1.这里只是例子程序,说   不定正规程序关掉了的 2.总要在fork之后才可以管,最好是一进父进程或子进   程就关,可是这里是函数,函数可能要调用多遍,不利于模块化 3.说不定不关也   不会有什么问题,高手总是一切尽在掌握中
应用举例2
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
popen第一个参数是一个命令字符串(最好全路径),第二个参数要么‘r’,要么‘w’
system貌似也可以执行一个命令啊,那有什么区别呢?
system是fork一个子进程后,在子进程中exec一个命令,就和我们在linux敲入一行命令是一样的
popen是创建一个管道连接到另一个进程,如果type参数是'r',返回的文件指针连接到command的标准输出,如果是‘w’,则为标准输入,并且是类似于文件的那种全缓冲模式
#include <stdlib.h>
#include < string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
int main()
{
      char buf[128];
      FILE *pp;

       if( (pp = popen( "ls -l", "r")) == NULL )
      {
                printf( "popen() error!\n");
                 exit(1);
       }
       system( "ls -l");
        while(fgets(buf, sizeof(buf), pp))
       {
                 printf( "%s", buf);
       }
       pclose(pp);
       return 0;
}
程序执行结果:
打印 ls -l 的结果,system和printf的结果一样,也就是说,popen没有本身里面的打印不输出罗哈
哎,具体是什么,明天再研究吧,今天先睡咯!
新的一天。。。。。。
今天下午继续比较,在网上找了点资料,发现也不尽人意,无非都是apue上的老调
重弹,可是本人看得不太懂,干脆不研究本质了,了解一下现象算了:
#include <stdio.h>
int main()
{
         sleep(10);
         printf( "tttttttttttttttttttttttttttt\n");
}
把该程序编译为 t 执行文件
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>


int main()
{
   FILE * ret;

   ret = popen( "./t", "r");
   //system( "./t");
   // while(!feof(ret))        printf( "%c",fgetc(ret));
   printf( "mmmmmmmmmmmmmmmmmmmmm\n");

   pclose(ret);
   return 0;
}
把这个文件也编译好,得到的执行文件和t执行文件在同一目录下
程序及程序结果联合分析:
1.popen这个函数并不阻塞主线程,所以它先打印mmmmmmmmmmmmmmmm,但是在       pclose的地方阻塞了,他一定要等到popen的那个执行完毕之后才算完
2.popen函数的标准输出不再直接输出了,而是以全缓冲的方式放到FILE里面来了
3.如果用的是system就不一样了,必须要等system里面的命令执行完毕了,才执行   下一句,也就是:先进入system,等10s,打印一串tttttttttttttttttt,再打   印mmmmmmmmmmmmmmmmmmmmmmmmm