管道
管道通信的流程:在一个进程中创建管道,创建子进程,关闭多余端口,使父子进程形成单向通道,进行数据传输。
创建匿名管道函数:
#include <unistd.h>
int pipe(int pipefd[2]);
示例:使用pip实现父子进程间通信,子进程作为写端,父进程读出内容并打印到终端。
解释:用到的write(int fd,const void *buf,size_t count)函数:把参数buf所指的内存写入count个字节到所指的文件fd内。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int tempFd[2];//定义文件描述符数组
int tempRet=pipe(tempFd);//创建管道
if(tempRet == -1){
perror("pipe");
exit(1);
}
pid_t tempPid=fork();
if(tempPid > 0){//父进程—读
close(tempFd[1]);//关闭写端
char tempBuf[64]={0};
tempRet = read(tempFd[0], tempBuf, sizeof(tempBuf));//读数据
close(tempFd[0]);
write(STDOUT_FILENO, tempBuf, tempRet);//将读到的数据写到标准输出
wait(NULL);
} else if(tempPid == 0){//子进程—写
close(tempFd[0]);//关闭读端
char *tempStr="There is content:hello,pipe\n";
write(tempFd[1], tempStr, strlen(tempStr)+1);//写数据
close(tempFd[1]);
}//of if
return 0;
}//of main
输出结果:子进程将内容写入管道,父进程从管道读出内容。
重定向函数:将参数oldfd的文件描述符传递给newfd
#include <unistd.h>
int dup2(int oldfd, int newfd);
示例:使用管道完成兄弟间通信,实现命令 ls | wc -l
解释一下命令 ls|wc-l 实现的功能:ls列出当前文件夹下的文件,通过管道传递内容实现统计管道传来的文件数量,如下:
通过代码程序实现命令功能:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
int tempFd[2];
int tempRet = pipe(tempFd);
if(tempRet == -1){
perror("pipe err");
exit(1);
}//of if
int i;
pid_t tempPid, tempWpid;
for(i=0; i<2; i++){//2个子
if((tempPid = fork()) == 0){
break;
}//of if
}//of if
if(2 == i){//父进程,回收子进程
close(tempFd[0]); //关闭读
close(tempFd[1]); //关闭写
tempWpid = wait(NULL);
printf("wait child 1 success,pid=%d\n", tempWpid );
tempPid = wait(NULL);
printf("wait child 2 success,pid=%d\n", tempPid);
} else if(0 == i){//子进程1—写
close(tempFd[0]);
dup2(tempFd[1], STDOUT_FILENO);//定向到标准输出
execlp("ls", "ls", NULL);
} else if(1 == i){//子进程2—读
close(tempFd[1]);
dup2(tempFd[0], STDIN_FILENO);
execlp("wc", "wc", "-l", NULL);
}//of if
return 0;
}//of main
运行结果:
linux标准I/O库中封装的两个函数完成管道通信:
#include <stdio.h>
//创建管道&#