做网站创业需要注册公司吗/seo服务外包价格
Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。 而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室 以及 BSD(加州大学伯克利分校的伯克利软件发布中心), 他们在进程间通信方面的侧重点有所不同;
-
前者对Unix早期的进程间通信手段进行了系统的改进和扩充, 形成了“system-V IPC”,通信进程局限在单个计算机内(同一个设备的不同进程间通讯);
-
而后者则跳过了该限制,形成了基于套接字(socket)的进程间通信机制(多用于不同设备的进程间通讯)。 Linux则把两者继承了下来,所以说Linux才是最成功的,既有“system-V IPC”,又支持“socket”。
消息队列、共享内存 和 信号量 被统称为 system-V IPC,V 是罗马数字5, 是 Unix 的AT&T 分支的其中一个版本,一般习惯称呼他们为 IPC对象,这些对象的操作接口都比较类似, 在系统中他们都使用一种叫做 key 的键值来唯一标识,而且他们都是“持续性”资源——即他们被创建之后, 不会因为进程的退出而消失,而会持续地存在,除非调用特殊的函数或者命令删除他们。
Linux的IPC对象(包括消息队列、共享内存和信号量)在内核内部使用链表维护, 不同的对象使用 IPC标识符
来标识,如消息队列标识符 msqid、共享内存标识符 shmid,信号量标识符 semid。
对于用户来说,内核提供了简洁的接口,不同的进程通过 IPC关键字(key)
即可访问具体的对象。
通过如下命令可以查看系统当前的IPC对象,没有使用的情况下可能为空:
1. 消息队列的基本概念
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。 我们可以通过发送消息来避免命名管道的同步和阻塞问题。
2. 消息队列与信号管道的对比
消息队列与信号的对比:
-
信号承载的信息量少,而消息队列可以承载大量自定义的数据。
消息队列与管道的对比:
-
消息队列跟命名管道有不少的相同之处,它与命名管道一样,消息队列进行通信的进程可以是不相关的进程, 同时它们都是通过发送和接收的方式来传递数据的。在命名管道中,发送数据用write(),接收数据用read(), 则在消息队列中,发送数据用msgsnd(),接收数据用msgrcv(),消息队列对每个数据都有一个最大长度的限制。
-
消息队列也可以独立于发送和接收进程而存在,在进程终止时,消息队列及其内容并不会被删除。
-
管道只能承载无格式字节流,消息队列提供有格式的字节流,可以减少了开发人员的工作量。
具体解释如下:
管道是一种进程间通信(IPC)机制,允许一个进程将数据写入管道,另一个进程从管道读取数据。管道只能承载无格式的字节流,这意味着管道中传输的数据是一个连续的字节序列,没有内在的结构或格式信息。开发人员需要自己定义和解析数据的格式,这通常会增加额外的编程工作。
无格式字节流的特征
- 连续字节序列:管道中的数据只是简单的字节流,没有内在的格式。
- 需要自定义协议:开发人员需要设计数据协议,确保写入和读取的数据能够被正确解析。例如,定义消息的起始和结束标记,或者使用固定长度的消息。
- 复杂性:对于复杂的通信场景,处理数据解析和错误检测的代码会变得复杂。
消息队列也是一种IPC机制,但与管道不同的是,消息队列提供了有格式的字节流。消息队列将数据组织成独立的消息,每条消息都有自己的格式和边界。操作系统或消息队列实现会自动处理消息的边界和格式,使得开发人员无需关心数据的分割和解析问题。
有格式字节流的特征
- 独立消息:每条消息都是独立的实体,有明确的边界和格式。
- 自动处理:消息队列系统会自动管理消息的边界,确保发送和接收的是完整的消息。
- 简化开发:开发人员可以直接发送和接收完整的消息,无需处理字节流的分割和解析,减少了开发工作量。
-
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级,接收程序可以通过消息类型有选择地接收数据, 而不是像命名管道中那样,只能默认地接收。
-
消息队列可以实现消息的随机查询,消息不一定要以先进先出的顺序接收,也可以按消息的类型接收。
消息队列的实现包括创建或打开消息队列、发送消息、接收消息和控制消息队列这4 种操作。
3. 消息队列函数说明
Linux内核提供了一系列函数来使用消息队列:
-
其中创建或打开消息队列使用的函数是msgget(),这里创建的消息队列的数量会受到系统可支持的消息队列数量的限制;
-
发送消息使用的函数是msgsnd()函数,它把消息发送到已打开的消息队列末尾;
-
接收消息使用的函数是msgrcv(),它把消息从消息队列中取走,与FIFO 不同的是,这里可以指定取走某一条消息;
-
最后控制消息队列使用的函数是msgctl(),它可以完成多项功能。
3.1. msgget()获取函数
收发消息前需要具体的消息队列对象,msgget()函数的作用是创建或获取一个消息队列对象, 并返回消息队列标识符。函数原型如下:
int msgget(key_t key, int msgflg);
若执行成功返回队列ID,失败返回-1。 它的两个输入参数说明如下:
-
key:消息队列的关键字值,多个进程可以通过它访问同一个消息队列。 例如收发进程都使用同一个键值即可使用同一个消息队列进行通讯。 其中有个特殊值IPC_PRIVATE,它用于创建当前进程的私有消息队列。
-
msgflg:表示创建的消息队列的模式标志参数,主要有IPC_CREAT,IPC_EXCL和权限mode
-
如果是
IPC_CREAT
为真表示:如果内核中不存在关键字与key相等的消息队列,则新建一个消息队列; 如果存在这样的消息队列,返回此消息队列的标识符。 -
而如果为
IPC_CREAT | IPC_EXCL
表示如果内核中不存在键值与key相等的消息队列,则新建一个消息队列; 如果存在这样的消息队列则报错。 -
mode指IPC对象存取权限,它使用Linux文件的数字权限表示方式,如0600,0666等。
这些参数是可以通过“|”运算符联合起来的,因为它始终是int类型的参数。如msgflag使用参数
IPC_CREAT | 0666
时表示, 创建或返回已经存在的消息队列的标识符,且该消息队列的存取权限为0666, 即消息的所有者,所属组用户,其他用户均可对该消息进行读写。 -
注意:
选项 msgflg 是一个位掩码,因此 IPC_CREAT、IPC_EXCL 和权限 mode 可以用位或的方式叠加起来, 比如:
msgget(key, IPC_CREAT | 0666);
表示如果 key 对应的消息队列不存在就创建, 且权限指定为 0666,若已存在则直接获取消息队列ID,此处的0666使用的是Linux文件权限的数字表示方式。权限只有读和写,执行权限是无效的,例如 0777 跟 0666 是等价的。
当 key 被指定为 IPC_PRIVATE 时,系统会自动产生一个未用的 key 来对应一个新的消息队列对象, 这个消息队列一般用于进程内部间的通信。
-
该函数可能返回以下错误代码:
-
EACCES:指定的消息队列已存在,但调用进程没有权限访问它
-
EEXIST:key指定的消息队列已存在,而msgflg中同时指定IPC_CREAT和IPC_EXCL标志
-
ENOENT:key指定的消息队列不存在同时msgflg中没有指定IPC_CREAT标志
-
ENOMEM:需要建立消息队列,但内存不足
-
ENOSPC:需要建立消息队列,但已达到系统的限制
-
4. 发送消息与接收消息
4.1. msgsnd()发送函数
这个函数的主要作用就是将消息写入到消息队列,俗称发送一个消息。函数原型如下:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数说明:
-
msqid:消息队列标识符。
-
msgp:发送给队列的消息。msgp可以是任何类型的结构体,但第一个字段必须为long类型, 即表明此发送消息的类型,msgrcv()函数则根据此接收消息。msgp定义的参照格式如下:
/*msgp定义的参照格式*/
struct s_msg{long type; /* 必须大于0,消息类型 */char mtext[1]; /* 消息正文,可以是其他任何类型 */
} msgp;
-
msgsz:要发送消息的大小,不包含消息类型占用的4个字节,即mtext的长度。
-
msgflg:如果为0则表示:当消息队列满时,msgsnd()函数将会阻塞,直到消息能写进消息队列; 如果为IPC_NOWAIT则表示:当消息队列已满的时候,msgsnd()函数不等待立即返回; 如果为IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。
-
返回值:如果成功则返回0,如果失败则返回-1,并且错误原因存于error中。错误代码:
-
EAGAIN:参数msgflg设为IPC_NOWAIT,而消息队列已满。
-
EIDRM:标识符为msqid的消息队列已被删除。
-
EACCESS:无权限写入消息队列。
-
EFAULT:参数msgp指向无效的内存地址。
-
EINTR:队列已满而处于等待情况下被信号中断。
-
EINVAL:无效的参数msqid、msgsz或参数消息类型type小于0。
-
msgsnd()为阻塞函数,当消息队列容量满或消息个数满会阻塞。若消息队列已被删除,则返回EIDRM错误; 若被信号中断返回E_INTR错误。
如果设置IPC_NOWAIT消息队列满或个数满时会返回-1,并且置EAGAIN错误。
msgsnd()解除阻塞的条件有以下三个条件:
-
消息队列中有容纳该消息的空间。
-
msqid代表的消息队列被删除。
-
调用msgsnd函数的进程被信号中断。
4.2. msgrcv()接收函数
msgrcv()函数是从标识符为msqid的消息队列读取消息并将消息存储到msgp中, 读取后把此消息从消息队列中删除,也就是俗话说的接收消息。函数原型:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数说明:
-
msqid:消息队列标识符。
-
msgp:存放消息的结构体,结构体类型要与msgsnd()函数发送的类型相同。
-
msgsz:要接收消息的大小,不包含消息类型占用的4个字节。
-
msgtyp有多个可选的值:如果为0则表示接收第一个消息,如果大于0则表示接收类型等于msgtyp的第一个消息, 而如果小于0则表示接收类型等于或者小于msgtyp绝对值的第一个消息。
-
msgflg用于设置接收的处理方式,取值情况如下:
-
0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待
-
IPC_NOWAIT:若在消息队列中并没有相应类型的消息可以接收,则函数立即返回,此时错误码为ENOMSG
-
IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息
-
IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字节,则把该消息截断,截断部分将被丢弃
-
-
返回值:msgrcv()函数如果接收消息成功则返回实际读取到的消息数据长度,否则返回-1,错误原因存于error中。错误代码:
-
E2BIG:消息数据长度大于msgsz而msgflag没有设置IPC_NOERROR
-
EIDRM:标识符为msqid的消息队列已被删除
-
EACCESS:无权限读取该消息队列
-
EFAULT:参数msgp指向无效的内存地址
-
ENOMSG:参数msgflg设为IPC_NOWAIT,而消息队列中无消息可读
-
EINTR:等待读取队列内的消息情况下被信号中断
-
msgrcv()函数解除阻塞的条件也有三个:
-
消息队列中有了满足条件的消息。
-
msqid代表的消息队列被删除。
-
调用msgrcv()函数的进程被信号中断。
4.3. msgctl()操作消息队列
消息队列是可以被用户操作的,比如设置或者获取消息队列的相关属性,那么可以通过msgctl()函数去处理它。函数原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数说明:
-
msqid:消息队列标识符。
-
cmd 用于设置使用什么操作命令,它的取值有多个:
-
IPC_STAT 获取该 MSG 的信息,获取到的信息会储存在结构体 msqid_ds类型的buf中。
-
IPC_SET 设置消息队列的属性,要设置的属性需先存储在结构体msqid_ds类型的buf中, 可设置的属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,储存在结构体msqid_ds中。
-
IPC_RMID 立即删除该 MSG,并且唤醒所有阻塞在该 MSG上的进程,同时忽略第三个参数。
-
IPC_INFO 获得关于当前系统中 MSG 的限制值信息。
-
MSG_INFO 获得关于当前系统中 MSG 的相关资源消耗信息。
-
MSG_STAT 同 IPC_STAT,但 msgid为该消息队列在内核中记录所有消息队列信息的数组的下标, 因此通过迭代所有的下标可以获得系统中所有消息队列的相关信息。
-
-
buf:相关信息结构体缓冲区。
-
返回值:
-
成功:0
-
出错:-1,错误原因存于error中,错误代码:
-
EACCESS:参数cmd为IPC_STAT,却无权限读取该消息队列。
-
EFAULT:参数buf指向无效的内存地址。
-
EIDRM:标识符为msqid的消息队列已被删除。
-
EINVAL:无效的参数cmd或msqid。
-
EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行。
-
-
5. 消息队列示例
接下来通过示例来讲解消息队列的使用,使用方法一般是:
发送者:
-
获取消息队列的 ID
-
将数据放入一个附带有标识的特殊的结构体,发送给消息队列。
接收者:
-
获取消息队列的 ID
-
将指定标识的消息读出。
当发送者和接收者都不再使用消息队列时,及时删除它以释放系统资源。
本次实验主要是两个进程(无血缘关系的进程)通过消息队列进行消息的传递, 一个进程发送消息,一个进程接收消息,并将其打印出来。
5.1. 发送进程
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>#define BUFFER_SIZE 512struct message
{long msg_type;char msg_text[BUFFER_SIZE];
};
int main()
{int qid;struct message msg;/*创建消息队列*/if ((qid = msgget((key_t)1234, IPC_CREAT|0666)) == -1){perror("msgget\n");exit(1);}printf("Open queue %d\n",qid);while(1){printf("Enter some message to the queue:");if ((fgets(msg.msg_text, BUFFER_SIZE, stdin)) == NULL){printf("\nGet message end.\n");exit(1);}msg.msg_type = getpid();/*添加消息到消息队列*/if ((msgsnd(qid, &msg, strlen(msg.msg_text), 0)) < 0){perror("\nSend message error.\n");exit(1);}else{printf("Send message.\n");}if (strncmp(msg.msg_text, "quit", 4) == 0){printf("\nQuit get message.\n");break;}}exit(0);
}
本代码重点说明如下:
-
第22行,调用msgget()函数创建/获取了一个key值为1234的消息队列,该队列的属性“0666”表示任何人都可读写, 创建/获取到的队列ID存储在变量qid中。
-
第47行,调用msgsndb()函数把进程号以及前面用户输入的字符串,通过msg结构体添加到前面得到的qid队列中。
-
第51行,若用户发送的消息为quit,那么退出循环结束进程。
5.2. 接收进程
接收进程示例如下:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>#define BUFFER_SIZE 512struct message
{long msg_type;char msg_text[BUFFER_SIZE];
};int main()
{int qid;struct message msg;/*创建消息队列*/if ((qid = msgget((key_t)1234, IPC_CREAT|0666)) == -1){perror("msgget");exit(1);}printf("Open queue %d\n", qid);do{/*读取消息队列*/memset(msg.msg_text, 0, BUFFER_SIZE);if (msgrcv(qid, (void*)&msg, BUFFER_SIZE, 0, 0) < 0){perror("msgrcv");exit(1);}printf("The message from process %ld : %s", msg.msg_type, msg.msg_text);} while(strncmp(msg.msg_text, "quit", 4));/*从系统内核中删除消息队列 */if ((msgctl(qid, IPC_RMID, NULL)) < 0){perror("msgctl");exit(1);}else{printf("Delete msg qid: %d.\n", qid);}exit(0);}
-
第23行,调用msgget()函数创建/获取队列qid。可以注意到,此处跟发送进程是完全一样的,无论哪个进程先运行, 若key值为1234的队列不存在则创建,把以实验时两个进程并没有先后启动顺序的要求。
-
第36行,在循环中调用msgrcv()函数接收qid队列的msg结构体消息,此处使用阻塞方式接收, 若队列中没有消息,会停留在本行代码等待。
-
第47行,若前面接收到用户的消息为quit,会退出循环,在本行代码调用msgctl()删除消息队列并退出本进程。
5.3. 编译及测试
示例代码分别位于配套代码仓库/system_programing/msg/的msg_send及msg_recv目录下, 将两个进程编译出来,分别运行即可,实验现象如下:
5.3.1. 发送进程
在发送消息进程运行的时候,会提示让你输入要发送的消息,随便什么消息都可以的,使用回车完成消息的输入。 输入quit或使用Ctrl+D、Ctrl+C可结束进程。
# 以下操作在 system_programing/msg/msg_send 代码目录进行
# 编译X86版本程序发送进程
make
# 运行X86版本程序发送进程
./build_x86/msg_send_demo# 输入消息测试,
Open queue 98345
Enter some message to the queue:embedfire
Send message.
Enter some message to the queue:test
Send message.
Enter some message to the queue:hello world
Send message.
# 发送quit消息并结束进程
Enter some message to the queue:quit
Send message.Quit get message.
5.3.2.查看消息队列
可以通过 ipcs -q 命令来查看系统中存在的消息队列,若以上队列没有关闭,它的查看结果如下:
# 查询系统当前存在的队列
ipcs -q# 以下为输出:
--------- 消息队列 -----------
键 msqid 拥有者 权限 已用字节数 消息
0x000004d2 98345 flyleaf 666 0 0# 可查看到key键值 0x04d2(1234),qid 98345 与进程中创建的一致。
5.3.3. 接收进程
打开一个新终端,编译及运行接收消息进程,当你从发送消息进程输入消息时(按下回车键发送), 接收消息进程会打印出你输入的消息,若无消息则接收进程会阻塞等待,接收到quit消息会退出进程。
# 以下操作在 system_programing/msg/msg_recv 代码目录进行
# 编译X86版本程序发送进程
make
# 运行X86版本程序发送进程
./build_x86/msg_recv_demo# 接收到的消息
Open queue 98345
The message from process 21023 : embedfire
The message from process 21023 : test
The message from process 21023 : hello world
The message from process 21023 : quit
Delete msg qid: 98345.
小提示:在本例子中,若发送进程不是通过quit消息退出(如Ctrl+C或Ctrl+D),则不会触发接收进程主动删除消息队列, 在这种情况下可通过
ipcs -q
命令查看到该消息队列依然存在,通过ipcrm -q [消息队列qid]
即可删除。
相关文章:

Linux系统编程(4):消息队列
Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。 而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室 以及 BSD(加州大学伯克利分校的伯克利软件发布中心), 他们在进程间通信方面的侧重点有所不同; 前…...

【初阶数据结构篇】单链表的实现(赋源码)
文章目录 单链表的实现代码位置概念与结构概念:结构: 链表的性质链表的分类单链表的实现单链表的创建和打印及销毁单链表的创建单链表的打印单链表的销毁 单链表的插入单链表头插单链表尾插单链表在指定位置之前插入数据单链表在指定位置之后插入数据 单…...

LeetCode 2844.生成特殊数字的最少操作(哈希表 + 贪心)
给你一个下标从 0 开始的字符串 num ,表示一个非负整数。 在一次操作中,您可以选择 num 的任意一位数字并将其删除。请注意,如果你删除 num 中的所有数字,则 num 变为 0。 返回最少需要多少次操作可以使 num 变成特殊数字。 如…...

昇思MindSpore 应用学习-基于 MindSpore 实现 BERT 对话情绪识别
基于 MindSpore 实现 BERT 对话情绪识别 模型简介 BERT全称是来自变换器的双向编码器表征量(Bidirectional Encoder Representations from Transformers),它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模…...

【初阶数据结构篇】顺序表和链表算法题
文章目录 顺序表算法题移除元素删除有序数组中的重复项合并两个有序数组 链表算法题移除链表元素反转链表链表的中间结点合并两个有序链表链表分割链表的回文结构 顺序表算法题 不熟悉顺序表的可以先了解一下 顺序表实现方法 移除元素 给你一个数组 nums 和一个值 val&#x…...

使用weex进行APP混合开发
Weex 是一个用于构建高性能原生应用的框架,它使用 Vue.js 的语法和组件模型,允许开发者使用 HTML、CSS 和 JavaScript 来编写应用,同时能够编译成原生应用。Weex 主要由阿里巴巴集团开发,并且已经被多个公司采用。 下面是使用 We…...

C++stl大根堆/小根堆的创建与记忆
priority_queue<int, vector<int>, greater<int>> heap; 这行代码在 C 中声明了一个优先队列 heap,其元素类型为 int,使用 vector<int> 作为其底层容器,并且指定了 greater<int> 作为比较函数对象。 这里的关…...

visual studio性能探测器使用案列
visual studio性能探测器使用案列 在visual studio中,我们可以使用自带的工具对项目进行性能探测,具体如下 1.选择性能探查器 Vs2022/Vs2019中打开方式: Vs2017打开方式: 注意最好将解决方案配置为:Release Debu…...

redis的代码开发
redis是什么? 前提:官网地址https://redis.io 1.Redis是一个开源的,key,value格式的,内存型数据结构存储系统;它可用作数据库、缓存和消息中间件。 value支持多种类型的数据结构如strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglo…...

嗷呜,就问你接不接?
...

避免过拟合,参数大模型强,正则让模型不要走偏
1、加入惩罚项L1【绝对值】 和L2【默认 平方】,降低噪音的影响,减少权重W的值 2、丢弃法 层与层之间加入噪音,只能在全连接层使用 无偏差加入噪音 p为丢弃的概率 x 当概率p是0 否则为除以(1-p) 丢弃概率p 一般为0.1 0.5 def drop_out(x…...

vue+element-ui的列表查询条件/筛选条件太多以下拉选择方式动态添加条件(支持全选、反选、清空)
1、此功能已集成到TQueryCondition组件中 2、最终效果 3、具体源码(新增moreChoose.vue) <template><el-popoverpopper-class"t_query_condition_more":bind"popoverAttrsBind"ref"popover"v-if"allcheckList.length>0"…...

LLM的训练与推断
LLM的训练与推断 目前比较流行的大模型一般都是自回归模型。在推理时,它类似于RNN,每次计算下一个token的概率。也就是说,如果除去最开始的输入情况下,最终推理长度为n的话,就需要计算n次。但是训练却是并行化的。 在…...

uniapp使用WebSocket uniapp使用WebSocket Uniapp整合WebSocket uniapp使用 websocket
uniapp使用WebSocket uniapp使用WebSocket Uniapp整合WebSocket uniapp使用 websocket 前言1、Socket.js2、main.js引入3、组件中调用 前言 代码中的示例只在 H5、APP环境下成功运行,小程序环境下如果无效,需要使用预编译 - 条件性的编译,适…...

SSH Exporter:基于Prometheus的远程系统性能监控神器
SSH Exporter English | 中文 介绍 SSH Exporter 是一个基于 Prometheus 规范的监控工具,通过 SSH 协议远程收集目标服务器的系统性能数据,如 CPU 使用率、内存使用情况、磁盘和网络 I/O 等,并将这些数据暴露为 Prometheus 格式的 metrics…...

Docker基础概念
Docker 是一个流行的容器化平台,它使开发者能够打包他们的应用程序及其依赖项到一个轻量级、可移植的容器中。这有助于确保应用程序无论在哪里运行都能获得一致的结果。以下是 Docker 的几个基础概念的详细解释: 1. Docker 镜像 (Image) 定义: Docker …...

小白进阶为大神
编程已成为当代大学生的必备技能,但面对众多编程语言和学习资源,新生们常常感到迷茫。如何选择适合自己的编程语言?如何制定有效的学习计划?如何避免常见的学习陷阱?今天,我就来分享一下这方面的经验和知识…...

2024最新Python和PyCharm的安装教程
Python和PyCharm的安装教程如下: Python安装教程 一、下载Python安装包 访问Python官方网站:Welcome to Python.org。 点击页面上方的“Downloads”链接。 在下载页面,选择“Windows”系统(以Windows系统为例)&…...

数据库死锁:深入解析与应对策略
在数据库管理系统中,死锁是一个常见且棘手的问题,它可能导致系统性能下降、事务延迟甚至完全阻塞。本文将深入探讨数据库死锁的概念、产生原因、检测方法以及预防与解决策略,帮助读者更好地理解和应对这一挑战。 一、什么是数据库死锁&#…...

Python入门宝藏《看漫画学Python》,495页漫画带你弄清python知识点!简单易懂 | 附PDF全彩版
华为出品的《看漫画学Python》全彩PDF教程是一本适合Python初学者的学习资料,通过漫画的形式将复杂的Python技术问题简单化,使学习过程更加生动有趣。以下是对该教程的内容简介、本书概要及本书目录的详细解析: 内容简介 《看漫画学Python》…...

Webshell管理工具:AntSword(中国蚁剑)
中国蚁剑是一款开源的跨平台网站管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。 通俗的讲:中国蚁剑是 一 款比菜刀还牛的shell控制端软件。 一、中国蚁剑下载 1. 下载 AntSword-Loader https://github.com/AntSwordP…...

Java 中的File类
路径分为绝对路径和相对路径。 相对路径肯定是相对谁来说的,一般是一个文件相对于另外一个文件而言的路径。 下面是一个例子,比如index.htm如何找到photo.jpg呢? c:/website/web/index.htmc:/website/img/photo.jpg 所以在index.htm中使用…...

java将map转json字符串或者再将json字符串转回map,java将对象转json字符串或者互想转换,对象集合和json字符串互转
1.导入hutool工具依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency>2.直接复制一下代码运行 import cn.hutool.json.JSONUtil;import java.util.Ar…...

数据库管理-第225期 Oracle DB 23.5新特性一览(20240730)
数据库管理225期 2024-07-30 数据库管理-第225期 Oracle DB 23.5新特性一览(20240730)1 二进制向量维度格式2 RAC上的复制HNSW向量索引3 JSON集合4 JSON_ID SQL函数5 优化的通过网络对NVMe设备的Oracle的原生访问6 DBCA支持PMEM存储7 DBCA支持标准版高可…...

提高生产效率:最佳7大Bug记录工具
本文将分享2024年值得关注的7款Bug记录工具:PingCode、Worktile、禅道、Tapd、CODING、JIRA、Bugzilla。 Bug的管理和跟踪是一个不断挑战的任务,而一个高效的Bug记录工具不仅可以提高团队的生产效率,还能显著降低项目延误的风险。选择合适的工…...

DDOS攻击学习 - kali初学
文章目录 本地ssh配置nmap(网络连接的工具)nmap -sP IP地址nmap -p 1-65535 -A IP地址主机发现Ping扫描端口扫描时序扫描常用扫描方式 指纹识别与探测全端口版本探测防火墙/IDS逃逸报文分段 信息收集IP信息收集WHOIS查询 数据库渗透测试MySQL列举数据库列举MySQL变量 发起请求目…...

【C++】类和对象——流插入和流提取运算符重载
目录 前言ostream和istream自定义类型的流插入重载自定义类型的流提取重载解决私有问题日期类总接口 前言 我们在上一节实现日期类时,在输入和输出打印时,经常会调用两个函数: void Insert()//输入函数{cin >> _year;cin >> _mo…...

Vmware ubuntu20.04 虚拟文件夹
目录 1.vmware 设置 2.ubuntu设置 1.vmware 设置 设置完成后我们开机 2.ubuntu设置 我们打开终端 输入命令 vmware-hgfsclient可以看到你当前的共享文件 然后我们输入以下命令,用于将共享文件夹挂载到虚拟机中 sudo vmhgfs-fuse .host:/ /mnt -o nonempty -o …...

人工智能学习笔记 - 初级篇Ⅱ - 图形可视化 - 第11节: 绘制带填充区域的图表
微信公众号:御风研墨 关注可了解更多。问题或建议,请公众号留言 文章目录 绘制带填充区域的图表应用背景准备工作操作步骤工作原理补充说明最后 绘制带填充区域的图表 应用背景 在数据可视化中,带填充区域的图表可以有效地表示数据范围、趋…...

使用STM32实现一个线性代数计算器
文章目录 背景挑战与困难如何整合编译?error: non-ASM statement in naked function is not supportederror: #pragma import is an ARM Compiler 5 extension, and is not supported by ARM Compiler 6error: redefinition of __FILE 改造demo中的cout改造delete运…...