linux学习:进程通信 管道

news/2024/10/18 14:22:51/

目录

例子1  父进程向子进程发送一条消息,子进程读取这条消息

例子2  mkfifo 函数创建一个命名管道

例子3    mkfifo 函数创建一个命名管道处理可能出现的错误

例子4   管道文件是否已存在

例子5   除了“文件已存在”进行处理

例子6   创建一个命名管道,并尝试打开它以进行读取

例子7   创建一个命名管道(FIFO),打开它用于读取数据,并循环读取来自管道的数据,直到程序被手动终止

例子8   持续写入特定消息到命名管道中直到达到指定次数后终止

例子9   打开一个已存在的命名管道(FIFO)以进行写操作


例子1  父进程向子进程发送一条消息,子进程读取这条消息

#include <stdio.h>  // 包含标准输入输出函数库
#include <unistd.h>  // 包含各种系统调用和基本的函数声明,如fork(), pipe(), read(), write()
#include <string.h> // 包含字符串处理函数库
#include <stdlib.h> // 包含标准库函数,如exit()int main()
{int fd[2];  // 用于存储管道的文件描述符,fd[0]用于读,fd[1]用于写int pid;  // 用于存储进程IDchar buf[128];  // 缓冲区,用于存储从管道读取的数据// 创建管道if(pipe(fd) == -1){printf("create pipe failed\n");return -1;  // 管道创建失败时,打印错误信息并退出程序}pid = fork();  // 创建子进程if(pid < 0){  // fork失败printf("create child failed\n");return -1;  // 进程创建失败时,打印错误信息并退出程序}else if(pid > 0){  // 父进程执行的分支sleep(3);  // 父进程等待3秒,确保子进程准备好接收数据printf("this is father\n");close(fd[0]);  // 父进程关闭管道的读端write(fd[1], "hello from father", strlen("hello from father"));  // 向管道写入数据wait();  // 等待子进程结束} else {  // 子进程执行的分支printf("this is child\n");close(fd[1]);  // 子进程关闭管道的写端read(fd[0], buf, 128);  // 从管道读取数据printf("read from father: %s\n", buf);  // 打印从父进程读取的数据exit(0);  // 子进程正常退出}return 0;  // 主程序正常结束
}

例子2  mkfifo 函数创建一个命名管道

#include <sys/types.h>  // 包含数据类型定义,如pid_t、mode_t
#include <sys/stat.h>   // 包含文件状态定义,用于文件操作,如mkfifo// 主函数入口
int main()
{// 使用mkfifo系统调用创建一个名为"./file"的命名管道// 参数 "./file" 是命名管道的路径和名称// 参数 0600 是设置文件的权限,表示只有所有者有读写权限// 0600 对应于八进制,实际权限是 -rw------- mkfifo("./file", 0600);return 0;  // 返回0,正常结束程序
}

例子3    mkfifo 函数创建一个命名管道处理可能出现的错误

#include <sys/types.h>  // 包含数据类型定义,如pid_t、mode_t
#include <sys/stat.h>   // 包含文件状态定义,用于文件操作,如mkfifo
#include <stdio.h>      // 包含标凈输入输出库函数// 主函数入口
int main()
{// 尝试创建一个名为"./file"的命名管道,设置权限为0600(只有所有者有读写权限)int ret = mkfifo("./file", 0600);// 判断mkfifo函数的返回值if(ret == 0){  // 如果返回值为0,说明命名管道创建成功printf("mkfifo success\n");  // 输出成功消息}if(ret == -1){  // 如果返回值为-1,说明命名管道创建失败printf("mkfifo failure\n");  // 输出失败消息perror("why");  // 使用perror输出错误原因,它会根据全局变量errno来描述错误详情}		return 0;  // 程序正常结束,返回0
}

例子4   管道文件是否已存在

#include <sys/types.h>  // 包含数据类型定义,用于多种系统调用
#include <sys/stat.h>   // 包含文件属性的定义,用于文件权限设置
#include <stdio.h>      // 包含标准输入输出函数库
#include <errno.h>      // 包含错误号定义,用于错误处理// 主函数入口
int main()
{// 尝试创建一个命名管道,路径为"./file",权限为0600(只有文件所有者有读写权限)if((mkfifo("./file", 0600) == -1) && errno == EEXIST){  // 如果创建失败且错误号为EEXIST(文件已存在)printf("mkfifo failure\n");  // 打印失败消息perror("why");  // 使用perror输出错误原因}else{if(errno == EEXIST){  // 如果创建管道时未进入第一个条件分支,但错误号仍然为EEXISTprintf("file exists\n");  // 打印文件已存在的消息} else {printf("mkfifo success\n");  // 否则打印成功创建管道的消息}}       return 0;  // 程序正常结束
}

例子5   除了“文件已存在”进行处理

#include <sys/types.h>  // 包含系统数据类型定义
#include <sys/stat.h>   // 包含文件状态和权限定义
#include <stdio.h>      // 包含标准输入输出函数库
#include <errno.h>      // 包含错误号定义,用于错误处理// 主函数入口
int main()
{// 尝试创建一个命名管道,路径为"./file",权限为0600(只有文件所有者有读写权限)if((mkfifo("./file", 0600) == -1) && errno != EEXIST){  // 如果创建失败且错误号不是EEXIST(文件已存在)printf("mkfifo failure\n");  // 打印失败消息perror("why");  // 使用perror输出具体的错误原因}// 如果创建失败但错误原因是文件已存在(EEXIST),则不执行任何操作,也不打印错误消息return 0;  // 程序正常结束
}

例子6   创建一个命名管道,并尝试打开它以进行读取

#include <sys/types.h>  // 包含系统数据类型定义
#include <sys/stat.h>   // 包含文件状态和权限定义
#include <stdio.h>      // 包含标准输入输出函数库
#include <errno.h>      // 包含错误号定义,用于错误处理
#include <fcntl.h>      // 包含文件控制系统调用,如open// 主函数入口
int main()
{// 尝试创建一个名为"./file"的命名管道,设置权限为0600(只有文件所有者有读写权限)if ((mkfifo("./file", 0600) == -1) && errno != EEXIST) {  // 如果创建失败且错误号不是EEXIST(文件已存在)printf("mkfifo failure\n");  // 打印失败消息perror("why");  // 使用perror输出具体的错误原因}// 如果创建命名管道成功或错误原因是文件已存在,继续执行// 打开刚创建的命名管道文件,以只读模式打开int fd = open("./file", O_RDONLY);if (fd == -1) {  // 检查文件是否成功打开perror("Open failed");  // 打开失败,输出错误信息return -1;  // 返回非零值表示程序异常结束}printf("open success\n");  // 打开成功,输出成功消息// 实际使用中应该在这里进行读取操作,然后处理数据// 不再使用文件时,应该关闭文件描述符close(fd);return 0;  // 程序正常结束
}

例子7   创建一个命名管道(FIFO),打开它用于读取数据,并循环读取来自管道的数据,直到程序被手动终止

#include <sys/types.h>  // 包含系统数据类型定义
#include <sys/stat.h>   // 包含文件状态定义,用于文件操作,如mkfifo
#include <stdio.h>      // 包含标准输入输出函数库
#include <errno.h>      // 包含错误号定义,用于错误处理
#include <fcntl.h>      // 包含文件控制系统调用,如openint main()
{char buf[30] = {0};  // 定义一个字符数组用于接收读取的数据,初始化所有元素为0int nread = 0;       // 用于存储read函数返回的实际读取字节数// 尝试创建命名管道"./file",权限设置为0600(只有文件所有者有读写权限)if ((mkfifo("./file", 0600) == -1) && errno != EEXIST) {printf("mkfifo failure\n");  // 如果创建失败并且错误不是因为文件已存在,打印失败消息perror("why");  // 使用perror输出错误的详细原因return -1;      // 创建失败,返回非零值表示程序异常结束}// 打开命名管道,只读模式int fd = open("./file", O_RDONLY);if (fd == -1) {  // 检查文件是否成功打开perror("Open failed");  // 打开失败,输出错误信息return -1;  // 返回非零值表示程序异常结束}printf("open success\n");  // 打开成功,输出成功消息// 循环读取管道中的数据while (1) {nread = read(fd, buf, 30);  // 从管道文件中读取最多30个字符到buf中if (nread == -1) {  // 检查读取是否成功perror("Read failed");  // 读取失败,输出错误信息close(fd);  // 关闭文件描述符return -1;  // 返回非零值表示程序异常结束}printf("read %d bytes from fifo, context: %s\n", nread, buf);if (nread == 0) {  // 如果没有数据可读(读到EOF)break;  // 退出循环}}close(fd);  // 循环结束后,关闭文件描述符return 0;  // 程序正常结束
}

例子8   持续写入特定消息到命名管道中直到达到指定次数后终止

#include <sys/types.h>  // 包含数据类型定义,如pid_t
#include <sys/stat.h>   // 包含文件状态定义,用于文件操作,如mkfifo
#include <stdio.h>      // 包含标准输入输出函数库
#include <errno.h>      // 包含错误号定义,用于错误处理
#include <fcntl.h>      // 包含文件控制系统调用,如open
#include <string.h>     // 包含字符串处理函数库
#include <unistd.h>     // 包含常用的系统调用,如sleepint main()
{int cnt = 0;  // 用于计数,记录已写入消息的次数char *str = "message from fifo";  // 定义要写入管道的消息// 尝试以只写模式打开名为"./file"的FIFOint fd = open("./file", O_WRONLY);if (fd == -1) {  // 检查文件是否成功打开perror("Open error");  // 打开失败,输出错误信息return -1;  // 程序异常退出}printf("write open success\n");  // 打开成功,打印确认消息// 循环写入数据到FIFOwhile(1){write(fd, str, strlen(str));  // 向FIFO写入字符串sleep(1);  // 每次写入后暂停1秒cnt++;  // 更新计数器if(cnt == 5){break;  // 当写入5次后跳出循环}}close(fd);  // 关闭FIFO文件描述符return 0;  // 程序正常结束
}

例子9   打开一个已存在的命名管道(FIFO)以进行写操作

#include <sys/types.h>  // 包含系统数据类型定义
#include <sys/stat.h>   // 包含文件状态定义,用于文件操作,如mkfifo
#include <stdio.h>      // 包含标准输入输出函数库
#include <errno.h>      // 包含错误号定义,用于错误处理
#include <fcntl.h>      // 包含文件控制系统调用,如openint main()
{// 尝试以只写模式打开名为 "./file" 的 FIFOint fd = open("./file", O_WRONLY);if (fd == -1) {  // 检查文件是否成功打开perror("Open error");  // 打开失败,输出错误信息return -1;  // 程序异常退出}printf("write open success\n");  // 打开成功,打印确认消息// 此处应添加写操作,但当前示例仅演示打开操作// 关闭文件描述符close(fd);return 0;  // 程序正常结束
}

http://www.ppmy.cn/news/1466211.html

相关文章

2024年最适合中小型企业的顶级12款CRM系统对比

适合中小企业的CRM系统包括&#xff1a;纷享销客、Zoho CRM、HubSpot CRM、Freshsales、Pipedrive、Monday Sales CRM、Salesmate、Capsule CRM、金蝶云CRM、用友CRM、有赞CRM、简信CRM。 在现代商业运营中&#xff0c;CRM&#xff08;客户关系管理&#xff09;系统已成为不可或…

小白跟做江科大32单片机之旋转编码器计次

原理部分按照下面这个链接理解即可y小白跟做江科大32单片机之对射式红外传感器计次-CSDN博客https://blog.csdn.net/weixin_58051657/article/details/139350487https://blog.csdn.net/weixin_58051657/article/details/139350487 实验过程 1.按照江科大老师给的电路图进行连接…

MySQL Doublewrite Buffer 有了解过吗?

引言&#xff1a;在数据库管理中&#xff0c;确保数据的完整性和一致性是至关重要的。然而&#xff0c;在持久化数据到磁盘的过程中&#xff0c;可能会遇到各种意外情况&#xff0c;如断电或系统崩溃&#xff0c;从而导致部分数据写入&#xff0c;而另一部分数据未能成功写入&a…

数据结构 实验 1

题目一&#xff1a;用线性表实现文具店的货品管理问题 问题描述&#xff1a;在文具店的日常经营过程中&#xff0c;存在对各种文具的管理问题。当库存文具不足或缺货时&#xff0c;需要进货。日常销售时需要出库。当盘点货物时&#xff0c;需要查询货物信息。请根据这些要求编…

eNSP——两台电脑通过一根网线直连通信

一、拓扑结构 二、电脑配置 ip和子网掩码&#xff0c;配置两台电脑处于同一网段 三、测试 四、应用 传文件等操作&#xff0c;可以在一台电脑上配置FTP服务器

PyTorch、显卡、CUDA 和 cuDNN 之间的关系

概述 PyTorch、显卡、CUDA 和 cuDNN 之间的关系及其工作原理可以这样理解&#xff1a; 显卡 (GPU) 显卡&#xff0c;特别是 NVIDIA 的 GPU&#xff0c;具有大量的并行处理单元&#xff0c;这些单元可以同时执行大量相似的操作&#xff0c;非常适合进行大规模矩阵运算&#x…

数据结构复习指导之交换排序(冒泡排序,快速排序)

目录 交换排序 复习提示 1.冒泡排序 1.1基本思想 1.2算法代码 1.3性能分析 2.快速排序 2.1基本思想 2.2算法代码 2.3性能分析 交换排序 复习提示 所谓交换&#xff0c;是指根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。 基于交换的排序算法很…

迅狐跨境电商系统源码:技术栈与多端集成

随着全球化贸易的不断深入&#xff0c;跨境电商系统源码成为了连接不同国家和地区消费者与商家的重要桥梁。本文将探讨跨境电商系统源码的技术栈以及如何通过多端集成来提升用户体验。 技术栈概览 跨境电商系统源码的技术栈是构建高效、稳定平台的基础。以下是构建跨境电商系…