/* 无名管道 */
1、概念:
管道是linux进程间通信的一种方式,其是利用管道“文件”作为不同进程之间的传输数据的媒介,而实现进程间的数据交换。
而无名管道pipe则是利用内核虚拟出来的管道“文件”来作为不同进程间数据传输通道,而并非实际存在真正意义上的文件。
特点:
1、
无名管道只能用于具有亲缘关系的进程之间的通信,并且要由父进程来创建。(eg:父子进程间通信)
2、通信方式是单工的,意味着要实现两个进程间的双向通信,必须建立两个管道。
3、
其存在于内核为其分配的内核空间在。
2、无名管道的用法:
1、创建无名管道:
pipe(int pipefd[2]);
该函数返回两个文件描述符:pipefd[0](指向读端),pipefd[1](指向写端)
2、写管道数据:
ssize_t write(int fd, const void *buf, size_t count);
3
、读管道数据:
ssize_t read(int fd, void *buf, size_t count);
4、关闭管道 :
int close(int fd);
3、例程如下:
/*
* Author : zengwenzheng
* Create time:2014-1-15
* Description:This file is to create a noname pipe
* and test the pipe ipc.
*/
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
/*
* The data structure which use to be translate
*/
typedef struct student
{
char name[20];
char class[10];
int age;
}student,*tystudent;
/*
*
*/
int main(void)
{
int pipefd[2];
int ret = pipe(pipefd);//create a noname pipe
if(ret < 0)//error
{
printf("create pipe fail !\n");
perror("pipe error");
exit(-1);
}
pid_t pid = fork(); //create child process
if(pid > 0)//parent process write message
{
close(pipefd[0]);//close the read port
tystudent stu = (tystudent)malloc(sizeof(student));
strcpy(stu->name,"wenzheng");
strcpy(stu->class,"class68");
stu->age = 22;
write(pipefd[1],stu,sizeof(student));//write data in the pipe
sleep(1);
}
if(pid == 0)//child process read the pipe
{
close(pipefd[1]);//close the write port
tystudent stu = (tystudent)malloc(sizeof(student));
read(pipefd[0],stu,sizeof(student));
printf("%s\n",stu->name);
printf("%s\n",stu->class);
printf("%d\n",stu->age);
}
wait(NULL);
}
/* 有名管道 */
1、概念:
与无名管道的不同之处在于,有名管道fifo的管道文件是真正意义上的文件,其由用户自定义分配。
特点:
1、
有名管道fifo可以用于任意不同进程间的通信,不仅仅局限于具有亲缘关系的进程之间。
2、
其存储路径是用户定义的,有名管道文件是真正意义上的文件。
2、有名管道的用法:
1、创建有名管道:
int mkfifo(const char *pathname, mode_t mode);
2、打开管道
:
int open(const char *pathname, int flags);
3、读写、关闭有名管道与操作无名管道一致。
3、创建有名管道(mkfifo)时错误返回信息:
EACCES One of the directories in pathname did not allow search (exe‐
cute) permission.
EEXIST pathname already exists. This includes the case where pathname
is a symbolic link, dangling or not.
ENAMETOOLONG
Either the total length of pathname is greater than PATH_MAX, or
an individual filename component has a length greater than
NAME_MAX. In the GNU system, there is no imposed limit on over‐
all filename length, but some file systems may place limits on
the length of a component.
ENOENT A directory component in pathname does not exist or is a dan‐
gling symbolic link.
以上只列出几种,其中需要稍加注意第2种,其用于判断创建的管道是否已经存在。
4、例程如下:聊天程序(客户端)
/*
* Filename : client.c
* Author : zengwenzheng
* Create time : 2014-1-15
* Description : This file is to create two namepipe
* the one is used to send message(child process),
* the other is used to receive message(parent process).
*/
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<strings.h>
#include<errno.h>
int main(void)
{
pid_t pid = fork();//create process
/* parent process */
if( pid > 0)
{
int ret = 0;
/* create name pipe2 */
ret = mkfifo("pipe2",0777);
if(( ret < 0)&&(errno != EEXIST))//create pipe2 fail
{
perror("mkfifo pipe2");
exit(-1);
}
/* read data from pipe2 */
int pipefd2 = open("pipe2",O_RDONLY);
if(pipefd2 < 0)//open error
{
printf("open pipe2 error !\n");
exit(-1);
}
char buffer[100];
while(1)
{
bzero(buffer,sizeof(buffer));
/* read data from pipe2 */
int num = read(pipefd2,buffer,sizeof(buffer));
if(num!=0)
{
printf("%s\n",buffer);
}
}
}
/* child process */
if(pid == 0)
{
int ret = 0;
/* create namepipe */
ret = mkfifo("pipe",0777);
if( (ret < 0)&&(errno != EEXIST))//create pipe fail
{
perror("create pipe");
exit(-1);
}
/* open namepipe by write */
int pipefd = open("pipe",O_WRONLY);
if(pipefd < 0) //open fail
{
printf("open pipe2 error !\n");
exit(-1);
}
char buffer[100];
while(1)
{
/* write into pipe */
bzero(buffer,sizeof(buffer));//clear buffer
scanf("%s",buffer);
write(pipefd,buffer,100);
}
}
}