#ifndef PIPE_H
#define PIPE_H
#include<unistd.h> //管道编程 用到的头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdarg.h>
#include<errno.h>
#include <sys/wait.h>
#include<fcntl.h>
#define BUFSIZE 1024
void client(int readfd,int writefd);
void server(int readfd,int writefd);
int g_pipe()
{
printf("[ process]P:%d\n",getpid());
pid_t pid; //进程ID
int loop;
int pipe1[2],pipe2[2]; // 定义两个非命名管道,每个管道包含两个描述符
// pipe[0],pipe[1] 前者用于打开来读,后者打开来写
if(pipe(pipe1)<0) // 成功返回0 不成功返回-1
printf("pipe1 fail");
if(pipe(pipe2)<0)
printf("pipe2 fail");
printf("[ process]P:%d\n",getpid());
if((pid=fork()) < 0) // 创建进程
printf("[fork:%d]: ",loop);
else if(pid == 0)
{ // child process
close(pipe1[1]); //管道1 关闭来写的功能
close(pipe2[0]); //管道2 关闭来写的功能
printf("[ process]P:%d\n",getpid());
server(pipe1[0],pipe2[1]);
exit(0);
//printf("[Child process]P:%d C:%d\n",getpid(),getppid());
}
// main process
close(pipe1[0]); //管道1 关闭读功能
close(pipe2[1]); //管道2 关闭来写功能
client(pipe2[0],pipe1[1]);
waitpid(pid,NULL,0);
return 0;
}
void client(int readfd,int writefd)
{
size_t len;
ssize_t n;
char buff[BUFSIZE];
printf("what ------\n");
fgets(buff,BUFSIZE,stdin);
//scanf("%s",buff);
len = strlen(buff);
if(buff[len -1]=='\n')
--len;
//buff[len] = '\n';
printf("%s\n",buff);
write(writefd,buff,len);
printf("%s\n",buff);
while((n=read(readfd,buff,BUFSIZE))>0)
write(STDOUT_FILENO,buff,n);
}
void server(int readfd,int writefd)
{
int fd;
ssize_t n;
char buff[BUFSIZE+1];
if((n=read(readfd,buff,BUFSIZE))==0)
printf("server read fail\n");
int size =strlen(buff);
buff[size]='\0';
printf("server |%s|\n",buff);
if((fd = open (buff,O_RDONLY))<0)
{
snprintf(buff+n,sizeof(buff)-n,"can't open,%s\n",strerror(errno));
n = strlen(buff);
write(writefd,buff,n);
}
else
{
while((n=read(fd,buff,BUFSIZE))>0)
{
printf("%s\n",buff);
write(writefd,buff,n);
}
close(fd);
}
}
#endif //!PIPE_H
pipe管道是半双工的,全双工管道(某些系统提供,不是posix标准)
popen 和 pclose 函数
作为另一个关于管道的例子,标准I/O函数提供了popen函数,它创建一个管道并启动另外一个进程,该进程要么从该管道读出标准输入,要么往该管道写入标准输出
#include<stdio.h>
FILE* popne(const cgar*command, const char* type);
返回:若成功则为文件指针,若出错则为NULL
int pclose(FILE *stream);
返回:若成功返回shell的终止状态,若出错返回-1
int g_popen()
{
size_t n;
char buff[BUFSIZE],command[BUFSIZE];
FILE *fp;
fgets(buff,BUFSIZE,stdin);
n = strlen(buff);
if(buff[n-1]=='\n')
n--;
snprintf(command,sizeof(command),"cat %s",buff);
fp = popen(command,"r");
while(fgets(buff,BUFSIZE,fp)!=NULL)
fputs(buff,stdout);
pclose(fp);
exit(0);
}
4.7 管道和FIFO的额外属性
一个描述符设置成非阻塞的方式(2种)
1调用open时指定O_NONBLOCK标志
writefd = open(FIFO1,O_WRONLY|O_NONBLOCK,0);
2 如果一个描述符已经打开,那么可以调用fcntl已启用O_NONBLOCK标志。对于管道来说必须使用这种技术因为管道没有open调用。在pipe调用中也无法指定O_NONBLOCK标志,使用fcntl时,我们先使用F_GETFL命令取得当前文件状态,将它与O_NONBLOCK标志按位或后,再使用F_SETFL命令存储这些文件状态:
int flags;
if((flags = fcntl(fd,F_GETFL,0))<0)
err_sys("F_GETFL error");
flags|=O_NONBLOCK;
if(fcntl(fd,F_SETFL,flags)<0)
err_sys("F_SETFL error");