欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

管道实现进程间通信

程序员文章站 2022-05-14 08:03:22
...

一、无名管道

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

三、总结

无名管道和有名管道都可以进行进程间通信,从而实现数据共享,但是,无名管道只适用于有关联的两进程之间,有名管道则可以在任意进程间实现交换数据,

相关标签: 通信