`
airu
  • 浏览: 267523 次
  • 性别: Icon_minigender_1
  • 来自: 云南
社区版块
存档分类
最新评论

管道管道管道

阅读更多
Unix的管道真的是很方便,我们经常这样用:

$ls -l|wc -l


用于统计一个目录下的文件数。这里如果详细说起来,涉及了进程组,会话的概念。当然最显眼的就是符号 | ,这是就是管道,下面我们说说上面的这句shell如何用c语言来写。为了更能说明问题,我们把结果写入一个文件中。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>

void error_quit(char *msg)
{
    fprintf(stderr,"%s\n",msg);
    exit(1);
}

int main(int argc, char *argv[])
{
        int fd[2]; //存放管道读写的描述符
        int new_fd; 

        if(pipe(fd)==-1)  //使用pipe创建管道,错误返回-1
	error_quit("pipe error");
//fork,dup和dup2都在 unistd.h 中申明
        switch(fork()){  // 偶然看到的写法,觉得新鲜。fork返回pid_t类型
        case -1: error_quit("fork error");
        case 0:  //子进程返回0
                /*
                close(1); //关闭标准输出,为了下一句能把子进程的管道写描述符复制到标准输出
                   
                dup(fd[1]); //把子进程管道写描述符复制到一个新的描述符中,由于上面关闭了标准输出,系统会选取最小的描述符作为新描述符                */
                dup2(fd[1],1);//这是另外一种写法。上面注释部分由于不是原子操作,所以可以用dup2函数,实现上面注释块的功能。
                close(fd[0]); //关闭掉不用的描述符
                close(fd[1]);
                execlp("ls","ls -l",0); //在子进程空间执行ls命令
                error_quit("try to exec ls");
                break;
        default:
                close(0);
                dup(fd[0]); //可以用dup2代替
                close(fd[0]);
                close(fd[1]);

                if((new_fd = open("result.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))<0)
//打开一个文件,使用系统调用open,在fcntl.h中申明
                error_quit("open result.txt error");
                close(1); //关闭标准输出
                dup(new_fd); //标准输出变成文件result.txt
                execlp("wc","wc","-l",0);
                error_quit("try to wc");
                break;
	}
	exit(0);

}


现在保存,编译文件 pipe_test.c
$gcc -c pipe_test.c
...
$gcc -g -o pt pipe_test.o
...
$./pt
$cat result.txt
$28

你也可以试试是不是和 ls -l|wc -l 一样呢?
注意,父子进程之间的通讯。如果我们的子进程没有准备好数据怎么办?
对于管道,如果写进程停止,那么读进程读到0,表示结束。
如果读进程先停止,那么写进程将会收到一个SIGPIPE的信号,并且wirte返回-1,把errno设置为 EPIPE。

这就是无名管道。当然还有更复杂的FIFO,有名管道。
这里主要是要注意 dup的使用,学习如何重定向。对了,这里还忘记说了,文件描述符,也就是上面的0,1,2,3这些,是进程表中的一个索引,他指向文件表,文件表说明了这个文件的各种属性。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics