IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 第三十八讲 管道 -> 正文阅读

[系统运维]第三十八讲 管道

第三十八讲 管道

一、无名管道(pipe)

1、函数介绍

函数名称函数功能头文件返回值
int pipe(int pipefd[2])创建无名管道unistd.h成功:0
失败:-1

2、特点

  1. 特殊文件,前面说过在 linux 下一切皆文件。而无名管道是一个没有名字的文件,无法使用 open 函数进行操作,但是可以使用 close 函数关闭。
  2. 只能通过子进程继承文件描述符的形式来使用
  3. 使用 write 和 read 函数对无名管道进行操作时,可能会阻塞进程
  4. 所有文件描述符被关闭之后,无名管道被销毁

3、使用步骤

  • 父进程创建无名管道
  • 创建子进程
  • close 无用端口(单方面传输数据可以这样)
  • 读写管道
  • 关闭管道描述符

4、使用示例

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
    pid_t pid;
    int pipeFd[2];
    int status;
    char readBuf[100];
    
    memset(pipeFd, '\0', sizeof(pipeFd));
    
    /*创建管道*/
    if(pipe(pipeFd) < 0)
    {
        printf("Create pipe failed!");
        return -1;
    }

    /*创建进程*/
    pid = fork();
    if(pid < 0)
    {
        printf("Create sub process failed!");
        return -1;
    }
    /*子进程监听管道消息*/
    if(pid == 0)
    {
        /*关闭写通道*/
        close(pipeFd[1]);
        /*读取管道消息*/
        memset(readBuf, '\0', sizeof(readBuf));
        /*这里是阻塞的*/
        if(read(pipeFd[0], readBuf, sizeof(readBuf)) > 0)
        {
            printf("Read data is :%s\r\n", readBuf);
        }
        close(pipeFd[0]);
        exit(0);
    }
    /*父进程向管道内写入消息*/
    if(pid > 0)
    {
        /*关闭读取通道*/
        close(pipeFd[0]);
        if(write(pipeFd[1], "hello!sub process!", strlen("hello!sub process!")) < 0)
        {
            printf("Write pipe failed!\r\n");
            exit(1);
        }
        else
        {
            printf("Write pipe success!\r\n");
            close(pipeFd[1]);
            wait(&status);
            exit(1);
        }
    }
    return 0;
}

二、有名管道

1、函数介绍

函数名称函数功能头文件返回值
int mkfifo(const char *filename, mode_t mode)创建有名管道sys/types.h
sys/stat.h
成功:0
失败:-1

2、特点

  • 有文件名,可以使用 open 函数打开s
  • 任意进程间数据传输
  • write 和 read 操作可能会阻塞进程
  • write 具有"原子性"(会先判断管道内空间是否足以将数据全部写入进去,如果空间足够再去写入管道)

3、使用步骤

  1. 创建有名管道(mkfifo)
  2. 需要传输数据的进程打开有名管道(open),然后读写管道(read/write)
  3. 操作完关闭管道(close)

4、示例

读取代码

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

int main(char *argc, char **argv)
{
    int fd;
    char readBuf[20];

    /* 等待管道是创建*/
    printf("Fifo read stard!\r\n");
    while(access("my_fifo", F_OK)/* 头文件 #include <fcntl.h> #include <unistd.h>*/ == -1)
    {
        printf("Fifo is not created\r\n");
        sleep(1); /*头文件 unistd.h*/
    }
    /*打开管道*/
    fd = open("my_fifo", O_RDONLY);
    if(fd < 0)
    {
        printf("Open fifo failed!\r\n");
        exit(0);
    }
    /*读取管道内数据*/
    memset(readBuf, '\0', sizeof(readBuf));
    if(read(fd, readBuf, sizeof(readBuf)) > 0)
    {
        printf("Write fifo data is:%s\r\n", readBuf);
    }
    
    /*关闭管道*/
    close(fd);
    return 0;
}

写入代码

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

int main(char *argc, char **argv)
{
    int fd;

    /* 判断管道是否存在*/
    if(access("my_fifo", F_OK) == -1)
    {
        printf("Fifo is not created, start create fifo\r\n");
        if(mkfifo("my_fifo", 0666) < 0)
        {
            printf("Create fifo failed!\r\n");
            exit(-1);
        }
        printf("Fifo is created\r\n");
    }
    /*打开管道*/
    fd = open("my_fifo", O_WRONLY);
    if(fd < 0)
    {
        printf("Open fifo failed!\r\n");
        exit(0);
    }
    printf("Open fifo success!\r\n");
    /*读取管道内数据*/
    if(write(fd, "Hello fifo!\r\n", strlen("Hello fifo!\r\n")) <= 0)
    {
        printf("Write fifo failed!\r\n");
        exit(-1);
    }
    /*关闭管道*/
    close(fd);
    return 0;
}

小提示

细心的朋友可能会发现,在单独执行读或者写管道函数的时候,程序会阻塞在 open 函数。这是因为需要在另一端打开管道函数才能退出阻塞。这个可以通过命令查看 man mkfifo 里面有介绍。这里搬上原文

Once  you have created a FIFO special file in this way, any process can
open it for reading or writing, in the same way as  an  ordinary  file.
However,  it  has to be open at both ends simultaneously before you can
proceed to do any input or output operations on it.  Opening a FIFO for
reading  normally  blocks  until some other process opens the same FIFO
for writing, and vice versa.  See fifo(7) for nonblocking  handling  of
FIFO special files.

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-11-29 16:40:48  更:2021-11-29 16:41:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 2:52:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码