管道
管道是进程通信的手段之一,管道实际上只存在内存的文件,对这个文件的操作是通过两个打开的文件描述符,
它们分别代表管道的两端,管道是一种特殊的文件,它不属于某种文件系统,它是独立文件系统,有自己的数据结构,
按照适用范围:分为无名管道和有名管道。
无名管道
特点:1)半双工,数据只能在一个方向上流动。
2)只能在具有血缘关系的进程间使用。
#include<unistd.h>
int pipe(int fd[2]);
成功-- 0,出错-- -1
fd 参数:返回的是文件描述符,fd[0] 读端,fd[1]写端。
1.如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0),而仍
然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就
像读到文件末尾一样。
2.如果有指向管道写端的文件描述符没关闭(管道写端的引用计数大于0),而持有管
道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数
据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
3.如果所有指向管道读端的文件描述符都关闭了(管道读端的引用计数等于0),这时
有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。讲
信号时会讲到怎样使SIGPIPE信号不终止进程。
4.如果有指向管道读端的文件描述符没关闭(管道读端的引用计数大于0),而持有管
道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时
再次write会阻塞,直到管道中有空位置了才写入数据并返回
FIFO(有名管道)
特点:1)两个无相关的进程之间可以通信
2)FIFO 是一种文件类型,通过stat结构的st_mode成员的编码可以知道文件是否是FIFO 类型。
#include<sys/stat.h>
int mkfifo(const char *path,mode_t mode);
成功-- 0,出错-- -1
FIFO 需要用open来打开,对他的I/O 处理和常规文件相似。
FIFO没有指定O_NONBLOCK,只读open要阻塞到某个其他进程为写而打开这个FIFO为止;类似的,只写open也是这样。
管道是进程通信的手段之一,管道实际上只存在内存的文件,对这个文件的操作是通过两个打开的文件描述符,
它们分别代表管道的两端,管道是一种特殊的文件,它不属于某种文件系统,它是独立文件系统,有自己的数据结构,
按照适用范围:分为无名管道和有名管道。
无名管道
特点:1)半双工,数据只能在一个方向上流动。
2)只能在具有血缘关系的进程间使用。
#include<unistd.h>
int pipe(int fd[2]);
成功-- 0,出错-- -1
fd 参数:返回的是文件描述符,fd[0] 读端,fd[1]写端。
1.如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0),而仍
然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就
像读到文件末尾一样。
2.如果有指向管道写端的文件描述符没关闭(管道写端的引用计数大于0),而持有管
道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数
据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
3.如果所有指向管道读端的文件描述符都关闭了(管道读端的引用计数等于0),这时
有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。讲
信号时会讲到怎样使SIGPIPE信号不终止进程。
4.如果有指向管道读端的文件描述符没关闭(管道读端的引用计数大于0),而持有管
道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时
再次write会阻塞,直到管道中有空位置了才写入数据并返回
#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc,char **argv)
{
int fd[2];
char buf[1024];
pid_t pid;
int n;
if(pipe(fd) < 0){
fprintf(stderr,"error: pipe ");
exit(1);
}
if( (pid = fork()) < 0){
fprintf(stderr,"error: fork");
exit(1);
}
else if(pid == 0){
close(fd[0]);//close read
while(1){
n = read(STDOUT_FILENO,buf,sizeof(buf));
write(fd[1],buf,n);
}
}
else{
close(fd[1]);
while(1){
n = read(fd[0],buf,sizeof(buf));
write(STDOUT_FILENO,buf,n);
}
wait(pid,NULL);
}
exit(0);
}
FIFO(有名管道)
特点:1)两个无相关的进程之间可以通信
2)FIFO 是一种文件类型,通过stat结构的st_mode成员的编码可以知道文件是否是FIFO 类型。
#include<sys/stat.h>
int mkfifo(const char *path,mode_t mode);
成功-- 0,出错-- -1
FIFO 需要用open来打开,对他的I/O 处理和常规文件相似。
FIFO没有指定O_NONBLOCK,只读open要阻塞到某个其他进程为写而打开这个FIFO为止;类似的,只写open也是这样。
FIFO制定 O_NONBLOCK,只读open立即返回,若没有进程为读打开FIFO ,返回 -1,并将errno设置为ENXIO。
client.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
#include<string.h>
#define MAXLINE 512
int main(int argc,char **argv)
{
int fd_rd,fd_wr;
char read_buf[MAXLINE],write_buf[MAXLINE];
int flags,n;
fd_wr = open("public_fifo",O_WRONLY);
fd_rd = open("usr1",O_RDONLY);
while(1){
fgets(write_buf,sizeof(write_buf),stdin);
write(fd_wr,write_buf,strlen(write_buf));
n = read(fd_rd,read_buf,sizeof(read_buf));
write(STDOUT_FILENO,read_buf,n);
}
exit(1);
}
server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<error.h>
#include<string.h>
#include<fcntl.h>
#define MAXLINE 512
int main(int argc,char **argv)
{
int fd_rd,fd_wr;
char read_buf[MAXLINE],write_buf[MAXLINE];
int i = 0,n;
fd_rd = open("public_fifo",O_RDONLY);
if(fd_rd < 0){
fprintf(stderr,"error: open");
exit(1);
}
fd_wr = open("usr1",O_WRONLY);
if(fd_wr < 0){
fprintf(stderr,"error: open");
exit(1);
}
while(1){
n = read(fd_rd,read_buf,sizeof(read_buf));
write(fd_wr,read_buf,n);
}
exit(0);
}