📜  进程间通信-命名管道(1)

📅  最后修改于: 2023-12-03 15:28:19.896000             🧑  作者: Mango

进程间通信-命名管道

在Unix/Linux操作系统中,进程之间的通信是很常见的操作,其中一种通信方式就是使用命名管道(Named Pipes)。

命名管道是一种命名的管道,它允许两个或多个进程通过文件系统共享数据。命名管道可以在不相关的进程之间进行通信,这些进程甚至可以运行在不同的主机之间,只要它们都可以访问相同的命名管道。

创建命名管道

在Unix/Linux操作系统中,我们可以使用mkfifo命令来创建命名管道。该命令的用法如下:

mkfifo named_pipe

其中,named_pipe是管道的名称。

在程序中,我们可以使用mkfifo()函数来创建命名管道,其原型如下:

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

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

其中,pathname是管道的名称,mode是管道的权限掩码。

下面是一个创建命名管道的示例代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    char *fifo_name = "/tmp/myfifo";
    int res = mkfifo(fifo_name, 0666);
    if (res == -1) {
        perror("mkfifo");
        exit(EXIT_FAILURE);
    }  
    
    return 0;
}
打开命名管道

在程序中,我们可以使用open()函数来打开命名管道。该函数的原型如下:

#include <fcntl.h>

int open(const char *pathname, int flags);

其中,pathname是管道的名称,flags是打开的方式,通常为O_RDONLY(只读方式)或O_WRONLY(只写方式)。

下面是一个示例代码,打开一个只写的命名管道:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    char *fifo_name = "/tmp/myfifo";
    int fd = open(fifo_name, O_WRONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }  
    
    return 0;
}
读写命名管道

在程序中,我们可以使用read()函数和write()函数来读写命名管道。这两个函数的原型与读写文件时的函数相同,不同之处在于,当管道中没有数据可以读取时,read()函数将阻塞,直到有数据可读;当管道已满时,write()函数将阻塞,直到有空间可写。

下面是一个示例代码,向一个只写的命名管道中写入数据:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main()
{
    char *fifo_name = "/tmp/myfifo";
    int fd = open(fifo_name, O_WRONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }  
    
    char *message = "Hello, Named Pipes!";
    int len = strlen(message);
    int res = write(fd, message, len);
    if (res == -1) {
        perror("write");
        exit(EXIT_FAILURE);
    }
    
    close(fd);
    return 0;
}

读取一个只读的命名管道中的数据,示例代码如下:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define BUFFER_SIZE 1024

int main()
{
    char *fifo_name = "/tmp/myfifo";
    int fd = open(fifo_name, O_RDONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }  
    
    char buff[BUFFER_SIZE];
    int len = read(fd, buff, BUFFER_SIZE);
    if (len == -1) {
        perror("read");
        exit(EXIT_FAILURE);
    }
    
    write(STDOUT_FILENO, buff, len);
    
    close(fd);
    return 0;
}
删除命名管道

在程序中,我们可以使用unlink()函数来删除已经创建的命名管道。该函数的原型如下:

#include <unistd.h>

int unlink(const char *pathname);

下面是一个示例代码,删除一个已经创建的命名管道:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
    char *fifo_name = "/tmp/myfifo";
    int res = unlink(fifo_name);
    if (res == -1) {
        perror("unlink");
        exit(EXIT_FAILURE);
    }  
    
    return 0;
}
总结

命名管道是一种方便的进程间通信方式,它允许不相关的进程之间通过文件系统共享数据。使用命名管道,我们可以创建命名的管道、打开管道、读写管道和删除管道。在使用命名管道时,需要注意管道的权限掩码、打开方式和数据的阻塞等问题。