管道实现进程间通信
一、无名管道
1、什么是管道?
管道用于相关进程间的通信,相当于一个传递工具;
1、特点
(1)无名管道是半双工的,在管道的一端只能进行读或者是写,二者不可同时进行;就像水管一样,从管子的一端留入水,另一端流出来,不可以两端同时流入或者流出;
(2)无名管道只能实现在相关的进程间共享数据
(3)使用fork或者execve创建的子进程继承了父进程的文件描述符,可用管道进行共享内存
2、打开和关闭
(1)打开
int pipe( int fd[2] );
//读入或写入数据,管道必须设置fd[2]
若管道建立成功,则打开两个文件描述符,并将值保存在fd[2]这个整数数组中;
注意:
fd[1]用于写入数据,
fd[0]用于读出数据。
若管道建立失败,则返回-1,并且设置errno;
(2)关闭
linux操作系统中,一切皆文件,管道也是文件,成为管道文件(p),所以关闭管道,和关闭文件的方式一样,使用close( ) ;
2、读写管道
和读写文件一样,使用write( )和read( )来实现管道文件写和读;
几乎不会在同一个进程中打开一个管道仅供进程自己使用,管道的本质是用来在进程间交换数据的, 对于一个进程来说,它本来就可以访问自己要通过管道共享的数据,和自己共享数据是没有意义的;
切记:不可以对一个管道的两端同时进行读或者写操作;
3、举个例子
$ vim pipe.c
/pipe.c*
#include<stdio.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(int arg, char* args[] )
{
int fd[2];//定义管道描述符
char buf[100];//存放管道收发数据
int len;//记录长度
pipe(fd);//打开管道
memset(buf, 0, sizeof(buf) );
int pid = fork();//通过fork创建进程
if(pid == 0)//子进程中
{
close( fd[1] );//关闭(写)第二个管道
while((len = read(fd[0],buf,sizeof(buf)))> 0)
{
write(STDOUT_FILENO, buf, len );//将buf内容写道标准输出上
}
close( fd[0] );
}
else//父进程
{
close(fd[0]);//关闭(读)第一个管道
strcpy(buf,"wangdaiwen is a beautiful girl!\n");
write(fd[1],buf,sizeof(buf) );//将buf中的内容写道管道fd[1]中
close(fd[1]);
waitpid(pid, NULL,0 );//等待子进程退出
}
return 0;
}
编译链接后的结果如下:
结果十分的清晰明了,但是,要知道是从父进程中写入数据,子进程读出;
优点:效率高,可以实现两个有关系的进程间通信
缺点:不能适用于任意两个进程
二、有名管道
有名管道有效的弥补了无名管道的不足之处,它适用于任何两个进程之间的数据交换;
1、特征
(1)有名管道一旦创建,就是持久的、稳定的、存于文件系统中;
(2)一个shell命令可以创建一个有名管道;
(3)mkfifo [option] name;//mkfifo创建了一个名为name的有名管道
举个例子:
(4)
cat < fifo1//cat 命令代表从fifo1 中读取数据
ls > fifo1//将ls命令输出的结果写入到fifo1中
2、创建fifo
int mkfifo(const char* pathname, mode_t mode );
//第一个参数const char* pathname,是创建管道的名称
//第二个参数mode_t mode,是八进制读写权限,如:
//0000代表p--- --- ---
//0777代表prwx rwx rwx
若创建成功,返回0;
失败则返回-1,并设置errno
举个例子:
int main(int arg, char* args[])
{
mkfifo("ffff", 0000);//0000创建的管道文件权限应该为p-- --- ---
return 0;
}
3、删除fifo
(1)方法1:在命令行输入rm + 管道文件名即可
如:$ rm fifo1
(2)方法2 :函数删除
int unlink(const char*pathname )
//成功返回0;
/失败返回-1,并设置errno
举个例子:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
int i = unlink("ffff");
if(i == -1)
{
printf(" strerror(errno)" );
}
return 0;
}
4、打开关闭fifo
int open(const char* pathname, int flag);
int close(int fd);
//打开和关闭跟普通文件的方式一样
//fifo两端使用前都必须打开
//若flag为O—RDONLY,将阻塞open的调用,直到另一进程写入数据,打开fifo为止
//若flag为O—WRONLY,将阻塞open的调用,直到另一进程读出数据,打开fifo为止
举个例子:
请查看本人下一篇博客,为您呈上链接:
https://blog.csdn.net/dai_wen/article/details/79778759
三、总结
无名管道和有名管道都可以进行进程间通信,从而实现数据共享,但是,无名管道只适用于有关联的两进程之间,有名管道则可以在任意进程间实现交换数据,
上一篇: Android动画-属性动画