1.pipe
管道是UNIX系统IPC的最古老形式,并且所有的UNIX系统都提供此种通信机制。管道有下列两种局限性:
a.历史上,它们是半双工的,现在某些系统提供全双工管道,但是为了最佳的可移植性,我们决不应预先假定系统使用此
特性。
b.它们只能在具有公共祖先的进程之间使用。通常一个管道由一个进程创建,然后该进程调用fork,此后父子进程之间可以
使用该管道。
(FIFO没有第二种局限性,UNIX域套接字和命名流没有这两种局限性)
管道是由调用pipe函数而创建的:
#include<unistd.h> int pipe(int filedes[2]); //成功则返回0,出错则返回-1.经由参数filedes返回两个文件描述符:filedes[0]为读而打开,filedes[1]为写而打开。filedes[1]的输出是filedes[0]的输入。
调用fork之后做什么取决于我们想要有的数据流的方向,对于从父进程到子进程的管道,父进程关闭管道的读端fd[0],子
进程则关闭写端fd[1]。
调用fork之后的半双工管道:
从父进程到子进程的管道:
为了构造从子进程到父进程的管道,父进程关闭fd[1],子进程关闭fd[0]。
当管道的一端被关闭后,下列两条规则其作用:
a.当读一个写端已经被关闭的管道时,在所有数据都被读取后,read返回0,指示达到了文件结束处。
b.如果写一个读端已经被关闭的管道,则产生信号SIGPIPE。如果忽略该信号或者捕获该信号并从其处理程序返回,则
write返回-1,errno设置为EPIPE。
在写管道是,常量PIPE_BUF规定了内核中管道缓冲区的大小,如果对管道调用write,而且要求写的字节数小于等于
PIPE_BUF,则此操作不会与其他进程对同一管道的write操作穿插进行。但是,若有多个进程同时写一个管道,而且
进程要求写的字节数超过PIPE_BUF字节数时,写操作的数据可能穿插。
实践:
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> int main(void){ int result,n; int fd[2]; pid_t pid; char line[256]; if(pipe(fd) < 0){ perror("pipe"); return -1; } if((pid = fork()) < 0){ perror("fork"); return -1; }else if(pid > 0){ //parent close(fd[0]); if(fd[1] != STDOUT_FILENO){ dup2(fd[1],STDOUT_FILENO); } execl("/bin/ls","ls",(char*)0); }else{ //child close(fd[1]); while((n =read(fd[0],line,256)) > 0){ if(write(STDOUT_FILENO,line,n) != n){ perror("write"); exit(-1); } } close(fd[0]); } return 0; }运行结果:
WinVNC.log
a.out
a.txt
b.txt
chlock
dtest
lock
lock.txt
在父进程中将管道描述符赋值为标准输出,所以在执行ls后,原本是写到标准输出的,现在写到fd[1]中。而子进程将读到
的内容显示到标准输出上。
2.popen和pclose函数
常见的操作时