mkfifo()命名管道-FIFO客户端 服务端模拟。*System V消息队列、信号量(信号灯)。

@bit::Shadow
✧(≖ ◡ ≖✿

目录

*C中的FILE与PCB的关系?

子进程初创时图解

命名管道

mkfifo()创建

unlink()删除管道文件

☆☆☆命名管道关闭的正确顺序:

模拟服务端与客户端交互:

服务端

客户端

MP4效果演示

注意点:

ERR_EXIT异常退出宏定义

[" \ "必须加?](#“ \ ”必须加?)

匿名管道与命名管道的总结

[System V前瞻](#System V前瞻)

[链接🔗System V共享内存内核级详解下篇](#链接🔗System V共享内存内核级详解下篇)

[System V消息队列(queue)](#System V消息队列(queue))

[System V信号量(Semaphoes)](#System V信号量(Semaphoes))

PV机制(原子性"二态性"):

信号量相关术语

临界区与非临界区的对比

"锁"区分临界区非临界区图解:

[System V信号量接口](#System V信号量接口)


*C中的FILE与PCB的关系?

概念 所在位置 管理者
FILE 结构体 用户空间 C 标准库(glibc)
file 结构体(内核) 内核空间 内核
文件描述符表 PCB 内(内核空间) 内核

子进程初创时图解

子进程初创:

部分独立,部分指向原内容区。

命名管道

原理:利用路径的唯一性,创建"伪文件"(命名管道)标识,来关联不同进程,实现进程间通信。

命名管道是一个特殊的文件,以权限符"p"标识,由于管道通信数据先进先出的性质常以FIFO来指示命名管道。

mkfifo()创建

指令:

bash 复制代码
mkfifo fifo

代码:

cpp 复制代码
int mkfifo(const char* pathname, mode_t mode);

pathname:要创建文件的路径+名字。

mode:权限设置。 0666

返回值:

-1:失败,错误码被设置

0:正常创建。

unlink()删除管道文件

指令:

bash 复制代码
unlink #管道文件名

代码:

cpp 复制代码
int unlink(const char* pathname);

命名管道分作读取端与写端,当读取端打开写入端没有打开时或写端打开读端没有打开时均会阻塞。阻塞在open()或read()

☆☆☆命名管道关闭的正确顺序:

cpp 复制代码
close(fd);      // 1. 先关闭文件描述符 不再占用此文件
unlink("fifo"); // 2. 再删除文件 删除目录项 文件引用计数-1到0时删除

模拟服务端与客户端交互:

实现服务端(Server)到客户端(Client)的信息发送"I'm father",客户端读取输出。

服务端

1.创建命名管道fifo

2.打开管道并写入

3.关闭fd删除命名管道

cpp 复制代码
//Server.cc
int Sever() {
    int n = mkfifo("fifo", 0666);
    if(n == -1)
    {
        perror("错误");
        exit(1);
    }
    // 打开 写入"I'm father"
    int fd = open("fifo", O_WRONLY);
    if(fd == -1)
    {
        perror("open\n");
        exit(1);
    }
    printf("打开成功准备写入");
    // 写入
    std::string s = "I'm father";
    write(fd, s.c_str(), s.size());
    printf("写入完毕\n");

    // 关闭
    close(fd);
    //删除
    unlink("fifo");
    return 0;
}

客户端

1.打开、读取。

2.输出关闭。

cpp 复制代码
//Client.cc
int Client() { 
    //打开
    int fd = open("fifo", O_RDONLY);
    if(fd == -1)
    {
        perror("open fail");
        exit(1);
    }
    // 读取
    char s[64] = {0};
    int n = read(fd, s, 63);
    if(n == -1)
    {
        perror("read failed");
        exit(1);
    }
    // 输出
    printf("客户端读取结果:%s\n", s);
    // 关闭
    close(fd);

    return 0; 
}

MP4效果演示

服务端写入信息,客户端读取

注意点:

1.mkfifo时若已经存在则失败。

2.读端open时未创建则失败。

3.写后要关闭+删除。

ERR_EXIT异常退出宏定义

由于以后及及现在的检验原理激增所以定义此宏就十分有必要。

使用do { ...... }while(0)循环的目的是使此宏得以适应各种逻辑语句内。像循环语句,条件语句等等。

cpp 复制代码
#define ERR_EXIT(str) \
do\
{\
    perror(m);\
    exit(EXIT_FAILURE);\
}while(0)

" \ "必须加?

是的因为宏是全替换。

匿名管道与命名管道的总结

匿名管道通过int pipe(int fds2);创建一fds0与fds1分别作管道的读端和写端 并分别占用该进程接下来的两个文件描述符fd,配合fork()使用以分支父子进程,若要实现单向通信,可以父进程读端关闭子进程写端 关闭。匿名管道是文件流无文件本身与磁盘分隔

命名管道通过int mkfifo(const char* pathname, mode_t mode);实现具有名字"伪文件"管道的创建,其打破了"相邻进程间通信"的限制,操作完全类似于文件操作但unlink(int fd);删除目录项。


System V前瞻

System V(通常读作 "System Five")是 Unix 操作系统历史上最重要的法定版本之一,由 AT&T 贝尔实验室于 1983 年首次发布。它不仅奠定了现代商业 Unix 的基础,其许多设计理念和机制至今仍深深影响着 Linux 和 macOS 等现代操作系统。

System V信号量(Semaphoes):用于多个进程对共享资源的访问,解决同步与互斥问题。++仅作简要介绍。++

System V消息队列:允许进程以消息链表(队列)的形式异步发送和接受数据块。++仅作简要介绍。++

链接🔗System V共享内存内核级详解下篇

System V消息队列(queue)

System V信号量(Semaphoes)

解决System V中进程间数据安全问题。

信号量介绍:

"信号量"又称"信号灯",是描述对资源(内存、共享内存)预订情况的量,若可用资源已经耗尽,则申请(再次预订)会失败并阻塞挂起。

"资源耗尽"的信号灯依据------PV机制(荷兰语:Proberen,尝试/申请 ,Verhogen,增加/释放)。

PV机制(原子性"二态性"):

例原本int sem = 16;

申请维护sem--,原子操作 P操作。

退出归还sem++,原子操作 V操作。

例,若sem = 1;仅有"1"和"0"两种状态,称为"二元信号量"。

信号量相关术语

临界资源:被保护起来的共享资源。

临界区:每个进程中访问临界资源的那段"代码"

非临界区:不涉及共享资源(如:全局变量、共享内存、硬件设备等)操作的代码区域

互斥:一种制约关系。当一个进程进入临界区使用资源时 ,其他资源必须等待,直到该进程退出临界区。(银行自用ATM机)

临界区与非临界区的对比

| 特性 | 临界区 (Critical Section) | 非临界区 (Non-critical Section) |
| 资源访问 | 访问共享资源(如修改公共变量、写日志文件) | 只访问局部变量或进行独立计算 |
| 并发冲突 | 多个线程同时进入会导致**数据竞争(Data Race)**或死锁 | 多个线程同时执行互不影响,完全安全 |
| 同步控制 | 必须加锁(如 MutexSemaphore)限制访问 | 无需任何锁,线程可以并发现行 |

执行时间 应当越短越好(减少其他线程的等待时间) 往往包含大量的业务逻辑、计算或I/O
"锁"区分临界区非临界区图解:
System V信号量接口

创建 int semget(key_t key, int nsems, int semflg);

控制 int sectl(int semid, int semnum, int cmd,......);

int semop(int semid ,struct sembuf* sops, size_t nsops);

感谢支持,持续更新

欢迎关注

相关推荐
郝学胜_神的一滴12 小时前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake
戴为沐14 小时前
Linux内存扩容指南
linux
zylyehuo1 天前
Linux 彻底且安全地删除文件
linux
用户805533698032 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297912 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
乘云数字DATABUFF2 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
卷无止境3 天前
C++ 的Eigen 库全解析
c++
卷无止境3 天前
现代 C++特性大盘点:一门脱胎换骨的老语言
c++·后端
郝学胜_神的一滴3 天前
CMake 27:缓存变量的特性、语法、类型与实操全解
c++·cmake
Web3探索者3 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh