【Linux】进程间通信(命名管道、共享内存、消息队列、信号量)

作者主页: 作者主页
本篇博客专栏:Linux
创作时间 :2024年11月2日


命名管道:
- 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
- 命名管道是一种特殊类型的文件
我们可以使用mkfifo命令来创建一个管道。

然后通过echo往里面写入一段内容:
![]()
回车之后管道不会关闭,在终端2查看可以发现他的内存大小仍然是0,当我们在管道2打印出内容后,管道就自动关闭了
当我们这样执行的时候,我们就可以发现在一直不停的打印我们输入到管道的内容
下面我们在程序里面建立一个管道:

返回值为0是成功,不为0就是失败。
下面是一个运用命名管道进行通信的例子:
Pipe.hpp:(这里是一些的共享的资源,包括路径,打开管道,关闭管道)
#include <iostream> #include <string> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> using namespace std;const string gpathname = "./myfifo"; const mode_t gmode = 0600; const int gdefault = -1; const int gsize = 1024; const int gForWrite = O_WRONLY; const int gForRead = O_RDONLY;int OpenPipe(int flag){int _fd = ::open(gpathname.c_str(), flag);if (_fd == -1){std::cerr << "open errno" << std::endl;return _fd;}return _fd;}void ClosePipeHelper(int fd){if (fd >= 0)::close(fd);}// class NamePipe // { // private:// public:// };// int CreateNamePipe(string pathname) // { // umask(0); // int n = mkfifo(pathname.c_str(), 0600); // if (n != 0) // { // std::cerr << "mkfifo errno" << std::endl; // return -1; // } // return n; // }// class NamePipe // { // public: // NamePipe() // { // } // ~NamePipe() // { // }// private: // const string fifo_path; // int _id; // int _fd; // };Server.hpp及Server.cc
#include "Pipe.hpp"class Init { public:Init(){umask(0);int n = ::mkfifo(gpathname.c_str(), gmode);if (n < 0){std::cerr << "mkfifo errno" << std::endl;return;}std::cout << "mkfifo success" << std::endl;}~Init(){int n = ::unlink(gpathname.c_str());if (n != 0){std::cerr << "unlink failed" << std::endl;}std::cout << "unlink success" << std::endl;}private: };Init init;class Server { public:Server() : _fd(gdefault){}bool OpenPipeForRead(){_fd = OpenPipe(gForRead);if (_fd < 0){std::cerr << "Open cerrno" << std::endl;return false;}return true;}int RecvPipe(std::string *out){char buffer[gsize];ssize_t n = ::read(_fd, buffer, sizeof(buffer) - 1);if (n > 0){buffer[n] = 0;*out = buffer;}return n;}void ClosePipe(){ClosePipeHelper(_fd);}~Server(){}private:int _fd; };#include "Server.hpp"int main() {Server s;// 打开管道s.OpenPipeForRead();string message;while (1){if (s.RecvPipe(&message) > 0){std::cout << "Client Say:" << message << std::endl;}else{break;}}std::cout << "Client quit,me too" << std::endl;// 关闭管道s.ClosePipe();return 0; }Client.hpp及Client.cc
#include "Pipe.hpp"class Client { public:Client() : _fd(gdefault){}bool OpenPipeForWrite(){_fd = OpenPipe(gForWrite);if (_fd < 0)return false;return true;}int SendPipe(const std::string &in){return ::write(_fd, in.c_str(), in.size());}void ClosePipe(){if (_fd >= 0){::close(_fd);}}~Client(){}private:int _fd; };#include "Client.hpp"int main() {Client c;c.OpenPipeForWrite();while (1){std::string message;std::cout << "Client Enter:" << std::endl;std::getline(std::cin, message);c.SendPipe(message);}c.ClosePipe();return 0; }
system V共享内存
system V IPC是一种本地通信方案。共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据

共享内存在系统中可以同时存在多份,供不同对进程进行通信。
共享内存不是简单的一段内存空间,它也要有描述并管理共享内存的数据结构和匹配算法。
共享内存函数
shmget 函数
该函数是系统调用,操作系统提供系统调用,让我们创建共享内存。

功能:用来创建共享内存
参数:
key:这个共享内存段名字(由用户形成)
size:共享内存大小
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
常见标志位组合和使用:
IPC_CREAT 、IPC_EXCL
IPC_CREAT:如果你要创建的共享内存不存在,就创建。如果存在,就获取该共享内存并返回。
IPC_EXCL:单独使用没意义,只有和IPC_CREAT组合才有意义
IPC_CREAT | IPC_EXCL:如果你要创建的共享内存不存在,就创建。如果存在,就出错返回。(如果成功返回,意味着这shm是全新的)
key,用来标志共享内存,可以让进程a和b找到共享内存。系统提供了随机生成key值的方法ftok
返回值:成功则返回共享内存段的标识码;失败返回-1
ftok函数:
ftok不是系统调用,通过我们提供路径和id(这两个值可以随便写)帮我们生成一个key值。我们给a、b两个进程提供同样的路径和id,调用ftok,就能形成同样的key,就能看到同一个共享内存了。
返回值:成功了就返回key值,失败就返回-1。
共享内存的释放
共享内存不随着进程的结束而自动释放,需要我们手动释放(指令或者其他系统调用),否则会一直存在,直到系统重启。
共享内存的生命周期随内核,文件的生命周期随进程。
我们可以通过指令ipcs -m 来查看共享内存
可以通过ipsrm -m shmid(自己得到)来释放共享内存
若不想通过指令释放,可以通过下面这个函数释放
shmctl 函数

shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值,如下图)
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1
传IPC_STAT可以获取共享内存的属性,传IPC_RMID可以删除共享内存。
key和shmid的比较
key:属于用户形成,内核使用的一个字段,用户不能用key来进行shm的管理。它是内核用来进行区分shm的唯一性的。
shmid:内核给用户返回的一个标识符,用来进行用户级对共享内存进行管理的id值。
shmat 函数
功能:将共享内存段连接到进程地址空间。
如果未来不想使用该共享内存,可以用shmdt去关联
参数
shmid: 共享内存标识
shmaddr:指定共享内存想挂接到哪个地址上
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回共享内存的起始地址;失败返回-1
shmdt 函数
功能:将共享内存段与当前进程脱离
参数
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段
接口使用例子
Client.cc
#include "Shm.hpp" #include "namedPipe.hpp"int main() {// 1. 创建共享内存Shm shm(gpathname, gproj_id, gUser);shm.Zero();char *shmaddr = (char *)shm.Addr();sleep(3);// 2. 打开管道NamePiped fifo(comm_path, User);fifo.OpenForWrite();// 当成stringchar ch = 'A';while (ch <= 'Z'){shmaddr[ch - 'A'] = ch;std::string temp = "wakeup";std::cout << "add " << ch << " into Shm, " << "wakeup reader" << std::endl;fifo.WriteNamedPipe(temp);sleep(2);ch++;}return 0; }Server.cc
#include "Shm.hpp" #include "namedPipe.hpp"int main() {// 1. 创建共享内存Shm shm(gpathname, gproj_id, gCreater);char *shmaddr = (char*)shm.Addr();shm.DebugShm();// 2. 创建管道NamePiped fifo(comm_path, Creater);fifo.OpenForRead();while(true){std::string temp;fifo.ReadNamedPipe(&temp);std::cout << "shm memory content: " << shmaddr << std::endl;}sleep(5);return 0; }Shm.hpp
#ifndef __SHM_HPP__ #define __SHM_HPP__#include <iostream> #include <string> #include <cerrno> #include <cstdio> #include <cstring> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h>const int gCreater = 1; const int gUser = 2; const std::string gpathname = "/home/whb/code/111/code/lesson22/4.shm"; const int gproj_id = 0x66; const int gShmSize = 4097; // 4096*nclass Shm { private:key_t GetCommKey(){key_t k = ftok(_pathname.c_str(), _proj_id);if (k < 0){perror("ftok");}return k;}int GetShmHelper(key_t key, int size, int flag){int shmid = shmget(key, size, flag);if (shmid < 0){perror("shmget");}return shmid;}std::string RoleToString(int who){if (who == gCreater)return "Creater";else if (who == gUser)return "gUser";elsereturn "None";}void *AttachShm(){if (_addrshm != nullptr)DetachShm(_addrshm);void *shmaddr = shmat(_shmid, nullptr, 0);if (shmaddr == nullptr){perror("shmat");}std::cout << "who: " << RoleToString(_who) << " attach shm..." << std::endl;return shmaddr;}void DetachShm(void *shmaddr){if (shmaddr == nullptr)return;shmdt(shmaddr);std::cout << "who: " << RoleToString(_who) << " detach shm..." << std::endl;}public:Shm(const std::string &pathname, int proj_id, int who): _pathname(pathname), _proj_id(proj_id), _who(who), _addrshm(nullptr){_key = GetCommKey();if (_who == gCreater)GetShmUseCreate();else if (_who == gUser)GetShmForUse();_addrshm = AttachShm();std::cout << "shmid: " << _shmid << std::endl;std::cout << "_key: " << ToHex(_key) << std::endl;}~Shm(){if (_who == gCreater){int res = shmctl(_shmid, IPC_RMID, nullptr);}std::cout << "shm remove done..." << std::endl;}std::string ToHex(key_t key){char buffer[128];snprintf(buffer, sizeof(buffer), "0x%x", key);return buffer;}bool GetShmUseCreate(){if (_who == gCreater){_shmid = GetShmHelper(_key, gShmSize, IPC_CREAT | IPC_EXCL | 0666);if (_shmid >= 0)return true;std::cout << "shm create done..." << std::endl;}return false;}bool GetShmForUse(){if (_who == gUser){_shmid = GetShmHelper(_key, gShmSize, IPC_CREAT | 0666);if (_shmid >= 0)return true;std::cout << "shm get done..." << std::endl;}return false;}void Zero(){if(_addrshm){memset(_addrshm, 0, gShmSize);}}void *Addr(){return _addrshm;}void DebugShm(){struct shmid_ds ds;int n = shmctl(_shmid, IPC_STAT, &ds);if(n < 0) return;std::cout << "ds.shm_perm.__key : " << ToHex(ds.shm_perm.__key) << std::endl;std::cout << "ds.shm_nattch: " << ds.shm_nattch << std::endl;}private:key_t _key;int _shmid;std::string _pathname;int _proj_id;int _who;void *_addrshm; };#endif
共享内存虽然速度上占有一定优势,但是共享内存对内存不会提供任何的保护机制,会导致数据不一致的问题,即双方不存在谁等谁的情况,比如我想传一个hello,可能我刚写入一个h就已经被读走了,这样就会导致数据不一致的问题,我们在访问共享内存时,没有任何系统调用,所以速度是所有IPC中最快的。
system V消息队列
- 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法
- 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
消息队列的接口的使用跟共享内存函数很像。
如果要发消息队列的数据,用:
如果要接收数据,用:
要查消息队列就用 ipcs -q ,它的指令跟共享内存就一字之差
system V信号量
信号量主要用于同步和互斥的。
System V 信号量是由内核维护的一组整数,它可以被多个进程同时访问和修改。每个信号量代表一个资源的可用数量,进程可以通过对信号量进行操作来控制对资源的访问。信号量的操作包括增加、减少和等待信号量的值达到某个特定条件等。
信号量特点:
- 原子性操作:信号量的操作是原子性的,这意味着多个进程同时对信号量进行操作时,系统会保证操作的完整性和一致性,不会出现部分操作完成而其他操作未完成的情况。
- 可用于同步和互斥:信号量可以用于实现进程间的同步和互斥。例如,可以使用信号量来确保多个进程不会同时访问同一个共享资源,或者确保一个进程在某个条件满足之前等待另一个进程完成某个任务。
- 内核维护:信号量是由内核维护的,这意味着即使进程崩溃或退出,信号量的值也不会丢失。当进程重新启动时,可以继续使用信号量来控制对共享资源的访问。
进程互斥
- 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥
- 系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源。
- 在进程中涉及到互斥资源的程序段叫临界区
多个执行流(进程),都能看到的一份资源:共享资源
被保护起来的资源:临界资源。 用互斥的方式进行保护。
互斥:任何时刻只能有一个进程在访问共享资源。
信号量的主要作用是用来保护共享资源的。经过保护,共享资源就变成临界资源。

假设上面的方格是电影院的座位。看电影时,只要有了票,位置就一定是你的,而不是谁先坐到就是谁的。 所以成功申请了信号量,即使不访问共享资源,也会留着一部分资源给你。
这里的信号量也叫多元信号量。
对共享资源的整体使用,即资源只有一个,也就是有人用了,别人就用不了了,即互斥。申请信号量时,这种信号量叫二元信号量。
信号量也是一个公共资源。
信号量本质是一个计数器,申请信号量时,计数器--,也叫P操作。释放信号量时,计数器++,也叫V操作。
信号量的操作
Linux中允许用户一次申请多个信号量,用信号量集保存,信号量集用数组来维护。
如果申请了多个信号量,上面的nsems就是申请的信号量的个数。
如果信号量不需要了,就用 semctl 。 semid就是要删除的信号量集,semnum就是要删除的信号量集的下标。
要对信号量进行PV操作,就用 semop 。
查看信号量,用 ipcs -s 。删除操作跟前面类似。
最后:
十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:
1.一个冷知识:
屏蔽力是一个人最顶级的能力,任何消耗你的人和事,多看一眼都是你的不对。
2.你不用变得很外向,内向挺好的,但需要你发言的时候,一定要勇敢。
正所谓:君子可内敛不可懦弱,面不公可起而论之。
3.成年人的世界,只筛选,不教育。
4.自律不是6点起床,7点准时学习,而是不管别人怎么说怎么看,你也会坚持去做,绝不打乱自己的节奏,是一种自我的恒心。
5.你开始炫耀自己,往往都是灾难的开始,就像老子在《道德经》里写到:光而不耀,静水流深。
最后如果觉得我写的还不错,请不要忘记点赞✌,收藏✌,加关注✌哦(。・ω・。)
愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚菜鸟逐渐成为大佬。加油,为自己点赞!
相关文章:
【Linux】进程间通信(命名管道、共享内存、消息队列、信号量)
作者主页: 作者主页 本篇博客专栏:Linux 创作时间 :2024年11月2日 命名管道: 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文…...
[Android]从FLAG_SECURE禁止截屏看surface
在应用中,设置activity的flag为FLAG_SECURE就可以禁止截屏,截屏出来是黑色的, 试验一下, 注意事项 影响: 设置 FLAG_SECURE 标志后,用户将无法对该Activity进行截屏或录制屏幕。这个标志会影响所有屏幕录…...
python 五子棋小游戏
1. 实现效果 Python五子棋小游戏 2. 游戏规则 规则说明,五子棋人机对战游戏规则如下: Ⅰ 默认规则 - 五子棋规则 对局双方:各执一色棋子,一方持黑色棋子,另一方持白色棋子。棋盘与开局:空棋盘开局…...
JeecgBoot集成工作流实战教程
Activiti是一个轻量级的工作流程和业务流程管理(BPM)平台,它主要面向业务人员、开发人员和系统管理员。这个平台的核心是一个快速且可靠的Java BPMN 2流程引擎。Activiti是开源的,并且基于Apache许可证进行分发。它可以运行在任何…...
第三十章 章节练习商品列表组件封装
目录 一、需求说明 二、技术要点 三、完整代码 3.1. main.js 3.2. App.vue 3.3. MyTable.vue 3.4. MyTag.vue 一、需求说明 1. my-tag 标签组件封装 (1) 双击显示输入框,输入框获取焦点 (2) 失去焦点,隐藏输入框 (3) 回显标签信息 (4) 内…...
NumPy 高级索引
NumPy 高级索引 NumPy 是 Python 中用于科学计算的核心库之一,它提供了一个强大的N维数组对象和许多用于操作这些数组的函数。在 NumPy 中,除了基本的索引和切片操作外,还提供了高级索引功能,这使得您可以以更加灵活和高效的方式访问和操作数组中的数据。本文将详细介绍 N…...
C/C++常用编译工具链:GCC,Clang
目录 GNU Compiler Collection GCC的优势 编译产生的中间文件 Clang Clang的特点 什么是LLVM? Clang编译过程中产生的中间表示文件 关于Clang的调试 C 编译工具链中有几个主要的编译工具,包括: GNU Compiler Collection (GCC…...
let和war的区别
let和war的区别 看不懂图片,可以看视频教程...
[CUDA] stream使用笔记
文章目录 1. stream一般用法2. stream与event:3. stream异常的排查4. stream的异步与同步行为 1. stream一般用法 cudaStream_t stream_; cudaStreamCreate(&stream_); // create stream // some operators running on this stream_ cudaStreamSynchronize(str…...
第二课:开发工具
在本课中,我们将介绍一些常用的C开发工具,并附上下载链接,帮助你选择合适的工具进行开发。 1. DEVC DEVC 是一个轻量级的C开发工具,适合初学者使用。它提供了基本的代码编辑、编译和调试功能。 下载链接: DEVC 下载 2. Visual…...
Vue 学习随笔系列十三 -- ElementUI 表格合并单元格
ElementUI 表格合并单元格 文章目录 ElementUI 表格合并单元格[TOC](文章目录)一、表头合并二、单元格合并1、示例代码2、示例效果 一、表头合并 参考: https://www.jianshu.com/p/2befeb356a31 二、单元格合并 1、示例代码 <template><div><el-…...
对于一个含有直流和交流分量的信号,如何使用示波器正确显示并测出直流电压值和交流电压峰峰值?
对于一个含有直流(DC)和交流(AC)分量的混合信号,使用示波器来正确显示和测量其直流电压值和交流电压峰峰值需要选择适当的设置和方法。以下是详细的步骤: 所需设备 示波器电压探头 步骤一:连…...
移动混合开发面试题及参考答案
目录 什么是混合开发(Hybrid App)? 混合开发(Hybrid App)与原生开发相比有什么优缺点? 优点 缺点 混合开发(Hybrid App)的兴起原因是什么? 市场竞争和成本控制需求 技术发展和资源整合 人才资源的考量 Web App、Native App 和混合开发(Hybrid App)的区别是…...
命令行工具开发秘籍:从零开始创建实用Python脚本(如何创建Python命令行工具)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 创建命令行工具的基础🔖 在非模块化的环境中🔖 在模块化环境中📝 打包和安装模块📝 使用命令行工具⚓️ 相关链接 ⚓️📖 介绍 📖 如何将自己的Python模块打包成一个可在命令行中直接执行的工具?…...
Python - PDF 分割成单页、PDF 转图片(PNG)
文章目录 PDF 分割成一页页的 PDFPDF 转 PNGPDF 分割成一页页的 PDF import fitz def split_pdf(pdf_path, save_dir):source_pdf = fitz.open(pdf_path)# 遍历source_pdf中的每一页,page_number从0开始计数 for idx...
【网络】套接字编程——TCP通信
> 作者:დ旧言~ > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:TCP网络服务器简单模拟实现。 > 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! > 专栏选自:…...
PyTorch实践-CNN-验证码识别
1 需求 GitHub - xhh890921/cnn-captcha-pytorch: 小黑黑讲AI,AI实战项目《验证码识别》 2 接口 含义 在optim.Adam接口中,lr参数代表学习率(Learning Rate)。学习率是优化算法中的一个关键超参数,它决定了在每次迭代…...
json和pb的比较
1.介绍 在数据序列化和通信领域,schema 指的是用于定义数据结构的模式或结构描述。它描述了数据的字段、类型、嵌套结构和约束,并在数据验证和解释上发挥重要作用。常见的 schema 格式包括 Protocol Buffers (proto)、JSON Schema、XML Schema 等。 Pr…...
Redis-基本了解
一、Redis 初识 Redis 是⼀种基于键值对(key-value)的NoSQL数据库,与很多键值对数据库不同的是,Redis 中的值可以是由string(字符串)、hash(哈希)、list(列表)…...
HarmonyOS第一课 06 构建更加丰富的页面-习题解析
判断题 1. Tabs组件可以通过接口传入一个TabsController,该TabsController可以控制Tabs组件进行页签切换。T 正确(True) 错误(False) 使用 this.tabsController.changeIndex(this.currentIndex); 可以切换页签 WebviewController提供了变更Web组件显示内容的接口…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...












要对信号量进行PV操作,就用 semop 。