管道通信,王明学learn

            管道通信

一、通讯目的

1、数据传输

  一个进程需要将数据发送给另一个进程。

2、资源共享

  多个进程之间共享同样的资源。

3、通知事件

  一个进程需要向另一个/组进程发送消息,通知它们发生了某事件。

4、进程控制

  有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变。

二、通讯发展

Linux进程间通信(IPC:interprocesscommunication)由以下几部分发展而来:

  1、UNIX进程间通信

  2、基于System V进程间通信

  3、POSIX进程间通信

  POSIX(Portable Operating System Interface)表示可移植操作系统接口。电气和电子工程师协会IEEE最初开发POSIX 标准,是为了提高UNIX 环境下应用程序的可移植性。然而,POSIX 并不局限于UNIX,许多其它的操作系统,例如Microsoft Windows都支持POSIX 标准。

三、通讯方式

Linux进程间通讯的主要方式有:

  1、无名管道(pipe)

  2、有名管道(FIFO)

  3、信号(signal)

  4、消息队列

  5、共享内存

  6、信号量

  7、套接字(socket)

四、管道通信

    一个进程在管道的尾部写入数据,另一个进程从管道的头部读出数据。管道包括无名管道和有名管道两种,前者只能用于父进程和子进程间的通信,后者可用于运行于同一系统中的任意两个进程间的通信。

管道通信特点:

  1.管道通讯是单向的,有固定的读端和写端。

  2.数据被进程从管道读出后,在管道中该数据就不存在了。

  3.当进程去读取空管道的时候,进程会阻塞。

  4.当进程往满管道写入数据时,进程会阻塞。

  5.管道容量为64KB(#definePIPE_BUFFERS16 include/linux/pipe_fs_i.h)

  在Linux系统中,无名管道一旦创建完成后,操作无名管道等同于操作文件。无名管道的读端被视作一个文件;无名管道的写端也被视作一个文件。

五、无名管道函数学习pipe

5.1 函数原形

  int pipe(int pipefd[2]);

5.2函数功能

  创建无名管道

5.3 所属头文件

  <unistd.h>

5.4 返回值

  成功:返回 0

  失败:返回-1

5.5 参数说明

  pipefd[2]返回两个文件描述符,两个元素分别指向两端

  pipefd[0]:指向管道读端

  pipefd[1]:指向管道写端

六、有名管道 

  有名管道又称为FIFO文件,因此我们对有名管道的操作可以采用操作文件的方法,如使用open,read,write等.

6.1FIFO文件对比普通文件

FIFO文件在使用上和普通文件有相似之处,但是也有不同之处:

  1.读取Fifo文件的进程只能以”RDONLY”方式打开fifo文件。

  2.写Fifo文件的进程只能以”WRONLY”方式打开fifo文件。

  3.Fifo文件里面的内容被读取后,就消失了。但是普通文件里面的内容读取后还存在。

当执行写fifo文件后则进程一直处于阻塞状态直到有进程去读取管道中的文件

6.2 创建有名管道

6.2.1 函数名

  mkfifo

6.2.2 函数原形

  int mkfifo(const char* pathname,mode_t mode);

6.2.3 函数功能

  创建fifo文件(有名管道)

6.2.4 所属头文件

  <sys/types.h>   <sys/stat.h>

6.2.5 返回值

  成功:返回 0

  失败:返回-1

6.2.6 参数说明

  pathname:要创建的fifo文件的名字(包含路径)

  mode:标明白创建fifo文件访问权限

6.3 删除有名管道

6.3.1 函数名

  unlink

6.3.2 函数原形

  int unlink(const char* pathname);

6.3.3 函数功能

  删除文件,包含fifo文件

6.3.4 所属头文件

  <unistd.h>

6.3.5 返回值

  成功:返回0

  失败:返回-1

6.3.6 参数说明

  指定要删除文件的名称(包含路径)

 编辑write.c

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
char *path ="myfifo";
int main()

{    
    int fd;
    int res;
    char *str = "hello world";
    res = mkfifo(path,0766);  //创建管道名为myfifo的文件

    if(res != 0)    //创建成功在函数返回的是0,失败为-1
    {
        printf("function nkfifo() calls failed.");
    }

    fd = open(path,O_WRONLY); //打开管道文件
    if(fd == -1)
    {
        printf("function open() calls failed.");
        return -1;
    }
    while(1)   //循环向管道写数据
    {
        res = write(fd,str,strlen(str));  //向管道文件里面写入内容
        if(res == -1)
        {
            printf("function write() calls failed.");
        }
    }
    printf("write ok.
");
    close(fd);     //关闭文件
    return 0;
}

gcc  write.c -o write 进行编译 

./write运行

编辑read.c

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>

int main()
{
    int fd;
    int res;
    char buf[4096];
    memset(buf,'',4096);
    fd = open("myfifo",O_RDONLY);  //open fifo file
    if(fd == -1)
    {
        printf("function open() calls failed.");
        return -1;
    }
    printf("This proceeding id=%d, fd=%d
",getpid(),fd);
    while(1)    //循环接受数据
    {
        read(fd,buf,sizeof(buf)); //read fifo into buffer, This is a blocking method
        printf("read : buf=%s
",buf);
    }
    close(fd);
    return 0;

}

gcc  read.c -o read
./read  进行运行

因为管道文件是特殊的文件,因此任何时候管道文件里面都是空的,实际上管道通信是通过内存交互的。

 

原文地址:https://www.cnblogs.com/wmx-learn/p/5302853.html