【Linux】管道的通信总结

一、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);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值