管道可用来相关进程间传递数据,FIFO是管道的变体,可用于任何进程间的通信。管道又被分为无名管道和有名管道
管道(无名管道)的创建,使用:
父子进程通信:
#include<stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include "error_functions.h"
#define BUF_SIZE 30
int main (int argc,char **argv)
{
int fd[2];
char buf[10];
int numRead;
if(argc!=2||strcmp(argv[1],"--help")==0)
{
usageErr("%s string\n", argv[0]);
}
if(pipe(fd))
{
errExit("pipe");
}
switch(fork())
{
case -1:
errExit("fork");
case 0:
if(close(fd[1]==-1))
{
errExit("clsoe--child");
}
while(1)
{
numRead=read(fd[0],buf,BUF_SIZE);
if(numRead==-1)
errExit("read");
if(numRead==0)
break;
if(write(STDOUT_FILENO,buf,numRead)!=numRead)
{fatal("child-partail/faild write");}
else
{
break;
}
}
write(STDOUT_FILENO,"\n",1);
if(close(fd[0])==-1)
{
errExit("close");
}
_exit(EXIT_SUCCESS);
default:
if(close(fd[0])==-1)
errExit("close");
sleep(5);
if(write(fd[1],argv[1],strlen(argv[1]))!=strlen(argv[1]))
fatal("parent - partial/failed write");
if(close(fd[1])==-1)
errExit("close");
wait(NULL);
exit(EXIT_SUCCESS);
}
}
用管道同步多个进程:
#include<stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include"curr_time.h"
#include "get_num.h"
#include "error_functions.h"
int main(int argc,char **argv)
{
int fd[2];
int j=0,dump;
if(argc<2||strcmp(argv[1],"--help")==0)
usageErr("%s sleep-time ...\n",argv[0]);
printf("%s Parent started \n",currTime("%T"));
if(pipe(fd)==-1)
errExit("pipe");
for(j=1;j<argc;j++)
{
switch(fork())
{
case -1:
errExit("fork");
case 0:
if(close(fd[0])==-1)
errExit("close");
sleep(getInt(argv[j],1,"sleep-time"));
//sleep(aoit(argv[j]));
printf("%s child %d (pipe =%ld) closing pipe\n",currTime("%T"),j,(long)getpid());
if(close(fd[1])==-1)
errExit("close");
_exit(EXIT_SUCCESS);
default:
break;
}
}
if(close(fd[1])==-1)
errExit("close");
if(read(fd[0],&dump,1)!=0)
fatal("patrnt didn't get EOF\n");
printf("%s parent read to go \n",currTime("%T"));
exit(EXIT_SUCCESS);
}
FIFO(有名管道):
FIFO与管道类似,差别在于FIFO在文件系统中拥有一个名称,打开方式与普通文件一样。好出就是能够在非相关的进程间通信。
$ mkfifo [ -m mode] pathname
pathname是创建的FIFO名称,-m选项用来指定权限mode,与chmod 类似。
用FIFO实现简单迭代服务器:
客户端:
#include<stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include"curr_time.h"
#include "get_num.h"
#include "error_functions.h"
#define SEVRER_FIFO "/tmp/seqnum_sv"
#define CLIENT_FIFO_Template "/tmp/seqnum_cl.%ld"
#define CLIENT_FIFO_NAME_LEN (sizeof(CLIENT_FIFO_Template)+20)
static char clientfifo[CLIENT_FIFO_NAME_LEN];
struct request{
pid_t pid;
int seqlen;
};
struct response{
int seqNum;
};
int main(int argc,char **argv)
{
int serverFd,clientFd;
struct request req;
struct response resp;
if(argc >1 && strcmp(argv[1],"--help")==0)
usageErr("%s [seq-len...]\n",argv[0]);
umask(0);
snprintf(clientfifo,CLIENT_FIFO_NAME_LEN,CLIENT_FIFO_Template,(long)getpid());
if(mkfifo(clientfifo,S_IRUSR|S_IWUSR|S_IWGRP)==-1)
{
errExit("mkfifo");
}
req.pid=getpid();
req.seqlen=(argc>1)?getInt(argv[1],GN_GT_0,"seq-len"):1;
serverFd=open(SEVRER_FIFO,O_WRONLY);
if(serverFd==-1)
errExit("open");
if(write(serverFd,&req,sizeof(struct request))!=sizeof(struct request))
errExit("can not write serverFd");
clientFd=open(clientfifo,O_RDONLY);
if(clientFd==-1)
errExit("can not open clientfifo");
if(read(clientFd,&resp,sizeof(struct response))!=sizeof(struct response))
fatal("can't read response from server");
printf("%d\n",resp.seqNum);
exit(EXIT_SUCCESS);
}
服务端:
#include<stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include"curr_time.h"
#include "get_num.h"
#include "error_functions.h"
#define SEVRER_FIFO "/tmp/seqnum_sv"
#define CLIENT_FIFO_Template "/tmp/seqnum_cl.%ld"
#define CLIENT_FIFO_NAME_LEN (sizeof(CLIENT_FIFO_Template)+20)
struct request{
pid_t pid;
int seqlen;
};
struct response{
int seqNum;
};
int main(int argc,char **argv)
{
int serverFd,clientFd,dummyFd;
char clientFifo[CLIENT_FIFO_NAME_LEN];
struct request req;
struct response resp;
int seqNum=0;
umask(0);
printf("123\n");
if(mkfifo(SEVRER_FIFO,S_IRGRP|S_IWGRP|S_IWUSR)<0)
{
errExit("mkfifo %s",SEVRER_FIFO);
}
printf("12\n");
serverFd=open(SEVRER_FIFO,O_RDONLY);
if(serverFd<0)
{
errExit("open %s",SEVRER_FIFO);
}
dummyFd=open(SEVRER_FIFO,O_WRONLY);
if(dummyFd<0)
{
errExit("open %s",SEVRER_FIFO);
}
//屏蔽信号SIGPIPE
if(signal(SIGPIPE,SIG_IGN)==SIG_ERR)
errExit("signal");
for(;;)
{
if(read(serverFd,&req,sizeof(struct request))!=sizeof(struct request))
{
continue;
}
printf("server req.pid=%ld",(long)req.pid);
snprintf(clientFifo,CLIENT_FIFO_NAME_LEN,CLIENT_FIFO_Template,(long)req.pid);
//
clientFd=open(clientFifo,O_WRONLY);
if(clientFd<0)
{
errMsg("open %s",clientFifo);
continue;
}
resp.seqNum=seqNum;
if(write(clientFd,&resp,sizeof(struct response))!=sizeof(struct response))
{
fprintf(stderr,"Error writing to FIFO %s \n",clientFifo);
}
seqNum+=req.seqlen;
}
}