Linux -- pipe管道

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rikeyone/article/details/88947829

函数接口

#include <unistd.h>
int pipe(int fd[2]);

成功返回0,错误返回-1

该函数会创建一个管道,其中返回的fd[0]为读而打开,fd[1]为写而打开,一般用法是父进程利用pipe创建管道后,使用fork创建子进程,这样父子进程各有一对fd用于读取和写入管道,为了进程间的通信,需要各自保留一个读接口和一个写接口用于交换信息。
它的特点:

  • 半双工,管道的一端只能用于读,另一端只能用于写
  • 只适合父子进程或者兄弟进程
  • 读一个对方关闭的管道,会返回0
  • 写一个对方关闭的管道,会返回出错,并设置EPIPE,同时会产生SIGPIPE信号。

示例

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define pr_debug(fmt,...)   do{ printf("[%ld] DEBUG: "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_info(fmt,...)    do{ printf("[%ld] INFO:  "fmt,(long)getpid(),##__VA_ARGS__); fflush(stdout); }while(0)
#define pr_err(fmt,...)     do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__);fflush(stdout); }while(0)
#define err_exit(fmt,...)   do{ printf("[%ld] ERROR: "fmt,(long)getpid(),##__VA_ARGS__); exit(1); }while(0)


static int fd1[2],fd2[2];

void sigpipe_handler(int signo)
{
	pr_info("catch signal SIGPIPE!\n");
}

int signal_setup(void)
{
	struct sigaction act, oact;

	act.sa_handler = sigpipe_handler;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);

	if (sigaction(SIGPIPE, &act, &oact) < 0)
		err_exit("sigaction error\n");
	return 0;
}

int main(int argc, char *argv[])
{
	int ret;
	char greet[20];
	pid_t pid;

	if (pipe(fd1) < 0)
		err_exit("pipe error\n");
	if (pipe(fd2) < 0)
		err_exit("pipe error\n");

	signal_setup();

	if ((pid = fork()) < 0) {
		err_exit("fork error\n");
	} else if (pid > 0) {
		close(fd1[0]);
		close(fd2[1]);
		memcpy(greet, "Hello, child!\n", 15);
		write(fd1[1], greet, strlen(greet) + 1);
		/* read blockly for child's message */
		read(fd2[0], greet, 16);
		pr_info("parent receive: %s\n", greet);
		waitpid(pid, NULL, 0);

		/* write to a closed pipe fd will trigger SIGPIPE */
		write(fd1[1], greet, strlen(greet) + 1);
		sleep(1);
	} else {
		close(fd1[1]);
		close(fd2[0]);
		memcpy(greet, "Hello, parent!\n", 16);
		write(fd2[1], greet, strlen(greet) + 1);
		/* read blockly for parent message */
		read(fd1[0], greet, 15);
		pr_info("child receive: %s\n", greet);
	}
	return 0;
}

运行结果如下:

$ ./pipe 
[25529] INFO:  parent receive: Hello, parent!
[25530] INFO:  child receive: Hello, child!
[25529] INFO:  catch signal SIGPIPE!

猜你喜欢

转载自blog.csdn.net/rikeyone/article/details/88947829