版权声明:本文为博主原创文章,未经博主允许不得转载。 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!