【Linux】管道的通信总结

来源:互联网 发布:java面试宝典2015版 编辑:程序博客网 时间:2024/06/01 19:05

一、popen


管道常见的操作是创建一个管道连接到另一个进程,然后读其输出或向其输入端发送数据

标准I/O库提供了函数popen, 该函数是:创建一个管道,调用fork产生一个子进程,关闭管道的不使用端,

执行一个shell以运行命令,然后等待命令终止。

#include <stdio.h>
FILE *popen(const char *command, const char *type);
返回:若成功则为文件指针,若出错则为NULL
如果type为r, 那么调用进程读进command的标准输出
如果type为w, 那么调用进程写到command的标准输入


测试代码:

#include <stdio.h>#include <string.h>int main(void){FILE *fp = NULL;char buff[1024] = {0};char command[1024] = {0};memset(command, 0x00, sizeof(command));snprintf(command, sizeof(command), "%s", "ls");fp = popen(command, "r");memset(buff, 0x00, sizeof(buff));while(fgets(buff, sizeof(buff), fp) != NULL){printf("buff[%s]\n", buff);memset(buff, 0x00, sizeof(buff));}fclose(fp);return 0;}

二、 pipe

int pipe(int fd[2]);返回两个文件描述符,fd[0]和fd[1], 前者打开来读,后者打开来写成功返回0, 出错返回-1

测试代码:

#include <stdio.h>#include <string.h>#include <unistd.h>int main(void){char writebuff[1024] = {0};char readbuff[1024] = {0};char readbuff2[1024] = {0};int pipe_in[2], pipe_out[2];pid_t pid;printf("start test_pipe\n");pipe(&pipe_in);// 创建父进程中用于读取数据的管道pipe(&pipe_out);// 创建父进程中用于写入数据的管道if ( (pid = fork()) == 0) {// 子进程    close(pipe_in[0]);// 关闭父进程的读管道的子进程读端    close(pipe_out[1]);// 关闭父进程的写管道的子进程写端    dup2(pipe_in[1], STDOUT_FILENO);// 复制父进程的读管道到子进程的标准输出    dup2(pipe_out[0], STDIN_FILENO);// 复制父进程的写管道到子进程的标准输入    close(pipe_in[1]);// 关闭已复制的读管道    close(pipe_out[0]);// 关闭已复制的写管道    // 从标准输入读取数据    read(STDIN_FILENO, readbuff2, sizeof(readbuff2));    // 使用exec执行命令     execl("/bin/sh", "sh", "-c", readbuff2, NULL);} else {// 父进程    close(pipe_in[1]);// 关闭读管道的写端    close(pipe_out[0]);// 关闭写管道的读端    // 向pipe_out[1]中写数据    snprintf(writebuff, sizeof(writebuff), "%s", "ls");    write(pipe_out[1],writebuff,strlen(writebuff));// 这里sleep 3秒,为了是确认子进程先执行完成    sleep(3);    // 从pipe_in[0]中读结果     read(pipe_in[0], readbuff, sizeof(readbuff));    printf("readbuff[%s]\n", readbuff);    close(pipe_out[1]);// 关闭写管道    close(pipe_in[0]);// 关闭读管道    // 使用wait系列函数等待子进程退出并取得退出代码     waitpid(pid, NULL,0);}return 0;}

三、socketpair

#include <sys/socket.h>int socketpair(int family, int type, int protocol, int socketfd[2]);返回0成功,返回-1出错family必须是AF_LOCAL或者AF_UNIX, type可以是SOCK_STREAM或者SOCK_DGRAM, protocol必须是0创建的两个套接字描述符sockefd[0]和sockefd[1]都是可读写


测试代码:
#include <stdio.h>#include <string.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <unistd.h>int main(void){char writebuff[1024] = {0};char readbuff[1024] = {0};int fd[2];pid_t pid;socketpair(AF_UNIX, SOCK_STREAM, 0, fd) ;// 创建管道if ( (pid = fork()) == 0) {// 子进程close(fd[0]);// 关闭管道的父进程端dup2(fd[1], STDOUT_FILENO);// 复制管道的子进程端到标准输出dup2(fd[1], STDIN_FILENO);// 复制管道的子进程端到标准输入close(fd[1]);// 关闭已复制的读管道// 使用exec执行命令execl("/bin/sh", "sh", "-c", "sort", NULL);} else {// 父进程close(fd[1]);// 关闭管道的子进程端// 往fd[0]中写数据snprintf(writebuff, sizeof(writebuff), "%s", "j am king\n");write(fd[0],writebuff,strlen(writebuff));memset(writebuff, 0x00, sizeof(writebuff));snprintf(writebuff, sizeof(writebuff), "%s", "i am queue\n ");write(fd[0],writebuff,strlen(writebuff));    // 通知对端数据发送完毕shutdown(fd[0], SHUT_WR);// 从fd[0]中读数据read(fd[0], readbuff, sizeof(readbuff));printf(" readbuff[%s]\n", readbuff);/* 读取剩余数据 */close(fd[0]);// 关闭管道// 使用wait系列函数等待子进程退出并取得退出代码 waitpid(pid, NULL,0);}}


0 0
原创粉丝点击