匿名管道(pipe)和命名管道(mkfifo)
进程间通信必须通过内核提供的通道。
1、匿名管道
匿名管道通过打开的文件描述符来标识的。——用于具有亲缘关系间进程之间的通信。
int pipe(int fds[2]);//返回值0表示成功,-1表示失败
fd[0]:读 fd[1]:写
写数据时要关闭读端
读数据时要关闭写端
2、命名管道
命名管道借助于文件系统实现,文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道。——用于具有非亲缘关系间进程之间的通信。
命名管道的打开规则:
如果当前打开操作是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
O_NONBLOCK enable:立刻返回成功
如果当前打开操作是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO
需要注意的是打开的文件描述符默认是阻塞的.
管道的创建
管道文件大小为0,没有亲缘关系的文件也能通过管道名,来取到该管道中的缓存。
//创建管道文件 int mkfifo(const char *name,mode_t mode)
//打开管道文件
int fd=open(name,O_RDONLY);读
int fd=open(name,O_WRONLY);写
3、匿名管道与命名管道的区别:
匿名管道实例1:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int pipefd[2];
pid_t pid;
char recv_buf[1024];
int len;
if(argc < 2)
{
perror("Usage error:");
exit(1);
}
if(pipe(pipefd) < 0)
{
perror("pipe()");
exit(1);
}
pid = fork();
if(-1 == pid)
{
perror("fork()");
exit(1);
}
if(0 == pid)
{
close(pipefd[1]);
while((len = read(pipefd[0],recv_buf,10)) > 0 )
write(1,recv_buf,len);
puts("\n");
close(pipefd[0]);
exit(0);
}
else
{
close(pipefd[0]);
write(pipefd[1],argv[1],strlen(argv[1]));
close(pipefd[1]);
wait(NULL);
exit(0);
}
exit(0);
}
匿名管道实例2:
/*
* 父进程通过命令行的方式输入文件路径名(argv[1])写入管道
* 子进程从管道中读取数据并输出到标准输出
*
* eg. ./pipe pipe.c
* ./pipe ./pipe.c
* ./pipe ./home/user/IPC/pipe.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int pipefd[2];
pid_t pid;
char recv_buf[1024];
char send_buf[1024];
int recv_len;
size_t send_len;
FILE *fp = NULL;
if(argc < 2)
{
perror("Usage error:");
exit(1);
}
if(pipe(pipefd) < 0)
{
perror("pipe()");
exit(1);
}
pid = fork();
if(-1 == pid)
{
perror("fork()");
exit(1);
}
if(0 == pid)
{
close(pipefd[1]);
while((recv_len = read(pipefd[0],recv_buf,10)) > 0 )
write(1,recv_buf,recv_len);
puts("\n");
close(pipefd[0]);
exit(0);
}
else
{
close(pipefd[0]);
fp = fopen(argv[1],"r");
if(NULL == fp)
{
perror("fopen()");
exit(1);
}
while((send_len = fread(send_buf,1,10,fp)) > 0)
write(pipefd[1],send_buf,send_len);
fclose(fp);
close(pipefd[1]);
wait(NULL);
exit(0);
}
exit(0);
}
命名管道实例:
公共头文件public.h:
#ifndef PUBLIC_H__
#define PUBLIC_H__
#define MKFIFO_NAME "tp"
#endif
写端代码(write.c):
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
#include "public.h"
#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(int argc, char *argv[])
{
mkfifo(MKFIFO_NAME, 0644);
int infd = open("Makefile", O_RDONLY);
if (infd == -1)
ERR_EXIT("open error");
int outfd;
outfd = open(MKFIFO_NAME, O_WRONLY);
if (outfd == -1)
ERR_EXIT("open error");
char buf[1024];
int n;
while ((n = read(infd, buf, 1024)) > 0)
write(outfd, buf, n);
close(infd);
close(outfd);
return 0;
}
读端代码(read.c):
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
#include "public.h"
#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(int argc, char *argv[])
{
int outfd = open("Makefile2", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (outfd == -1)
ERR_EXIT("open error");
int infd;
infd = open(MKFIFO_NAME, O_RDONLY);
if (infd == -1)
ERR_EXIT("open error");
char buf[1024];
int n;
while ((n = read(infd, buf, 1024)) > 0)
write(outfd, buf, n);
close(infd);
close(outfd);
unlink(MKFIFO_NAME);
return 0;
}
PS:部分内容来源于其他博客,侵权删。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)