Linux进程通信--共享内存

共享内存

共享内存概念

共享内存允许两个或者多个进程共享物理内存的同一块区域(通常被称为段)。由于

一个共享内存段会成为一个进程用户空间的一部分,因此这种 进程间通信(IPC) 机制无需内核介

。所有需要做的就是让一个进程将数据复制进共享内存中,并且这部分数据会对其

他所有共享同一个段的进程可用。

◼ 与管道等要求发送进程将数据从用户空间的缓冲区复制进内核内存和接收进程将数据

从内核内存复制进用户空间的缓冲区的做法相比,这种 IPC 技术的速度更快。

共享内存使用步骤

获取

调用 shmget() 创建一个新共享内存段或取得一个既有共享内存段的标识符(即由其

他进程创建的共享内存段)。这个调用将返回后续调用中需要用到的共享内存标识符。

关联

◼ 使用 shmat() 来附上共享内存段,即使该段成为调用进程的虚拟内存的一部分。

◼ 此刻在程序中可以像对待其他可用内存那样对待这个共享内存段。为引用这块共享内存,

程序需要使用由 shmat() 调用返回的 addr 值,它是一个指向进程的虚拟地址空间

中该共享内存段的起点的指针。

分离

◼ 调用 shmdt() 来分离共享内存段。在这个调用之后,进程就无法再引用这块共享内存

了。这一步是可选的,并且在进程终止时会自动完成这一步。

删除

◼ 调用 shmctl() 来删除共享内存段。只有当当前所有附加内存段的进程都与之分离之

后内存段才会销毁。只有一个进程需要执行这一步

共享内存操作函数

ftok

ftok() 是 Unix 和类 Unix 系统中的一个函数,用于生成一个 System V IPC 键(key_t 类型),这个键通常用于 shmget()semget()msgget() 函数来创建和访问进程间通信(IPC)资源,如共享内存、信号量或消息队列。ftok() 函数通过结合一个文件的存在和一个唯一的标识符来生成这个键,旨在创建一个尽可能唯一的键。

函数原型

ftok() 的函数原型定义在 <sys/ipc.h> 头文件中,具体如下:

key_t ftok(const char *pathname, int proj_id);
  • pathname: 一个现存文件的路径名,这个文件必须对调用进程可访问,因为 ftok() 需要获取文件的 inode 编号。该文件的实际内容不重要,只需保证文件存在。
  • proj_id: 一个非零的整数,通常是一个小整数(比如 1, 2, 3 等)。它用于与 pathname 指定的文件的 inode 编号相结合,生成一个唯一的键。
返回值
  • 成功: 返回一个 key_t 类型的值,该值可用于 System V IPC 函数。
  • 失败: 返回 (key_t) -1 并可能设置 errno
错误处理

ftok() 可能会因为以下原因失败:

  • errno = EACCES: 调用进程没有访问指定 pathname 文件的权限。
  • errno = ENOENT: 指定的 pathname 文件不存在。
示例用法

以下是一个使用 ftok() 生成 IPC 键的示例,然后使用该键来创建共享内存:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>int main() {const char *path = "/tmp/somefile";int proj_id = 65;  // 项目标识符key_t key = ftok(path, proj_id);if (key == -1) {perror("ftok failed");return 1;}int shmid = shmget(key, 1024, 0644 | IPC_CREAT);if (shmid == -1) {perror("shmget failed");return 1;}printf("Key: %d, Shared memory segment ID: %d\n", key, shmid);return 0;
}

在这个程序中:

  • 通过指定 /tmp/somefile 文件和一个项目标识符 65ftok() 生成一个唯一的键。
  • 这个键然后被用来通过 shmget() 创建一个共享内存段。

ftok() 被广泛用于生成 IPC 键,因为它可以提供一种相对简单且通常有效的方式来生成在系统范围内唯一的键。然而,生成的键并不保证绝对唯一,尤其是在大型系统中或者多个应用使用相似的 proj_id 和文件路径时可能会发生冲突。

shmget

shmget() 是 Unix 和类 Unix 系统中 System V 共享内存 API 的一个函数,用于创建新的共享内存段或获取现有的共享内存段的标识符。这个函数是进行进程间通信(IPC)中共享内存使用的**第一步,**它允许多个进程通过访问同一块物理内存来交换信息,从而实现高效的数据通信。

函数原型

shmget() 函数的原型定义在 <sys/shm.h> 头文件中,其基本语法如下:

int shmget(key_t key, size_t size, int shmflg);
  • key: 用于唯一标识共享内存段的键。这个键可以是任意的 key_t 类型的值,通常使用 ftok() 函数从一个文件名和一个整数生成,以确保键的唯一性。另外,可以指定 IPC_PRIVATE 作为键值来创建一个新的、无法通过键值访问的共享内存段,只能通过进程间继承或通过返回的共享内存标识符来访问。

  • size: 共享内存段的大小,单位是字节。这个参数指定了需要分配的内存容量。

  • shmflg: 操作标志,这个标志由一组位标志组合而成,用来设置内存段的访问权限和状态。这些标志包括权限位(如 06440666 等),以及可能包含的 IPC_CREATIPC_EXCLIPC_CREAT 表示如果指定的键没有对应的共享内存段,则创建一个新的内存段。如果同时指定了 IPC_EXCL,在键已经有对应的共享内存段存在的情况下,shmget() 会失败。

返回值
  • 成功: 返回一个整数,这个整数是共享内存段的标识符(shmid),用于后续的 shmat()shmdt()shmctl() 等操作。
  • 失败: 返回 -1,并设置 errno 以指示错误类型。常见的 errno 值包括 EINVAL(参数无效)、EEXIST(已存在具有相同键的共享内存段,且使用了 IPC_EXCL)、ENOENT(指定的键不存在,且没有指定 IPC_CREAT)、EACCES(权限错误)等。
示例用法

这里是一个创建共享内存段的基本示例:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>int main() {key_t key = ftok("somefile", 65);  // 生成唯一键int shmid = shmget(key, 1024, 0644 | IPC_CREAT);if (shmid == -1) {perror("shmget failed");return 1;}printf("Shared memory segment created with ID: %d\n", shmid);return 0;
}

在这个示例中,ftok() 函数用于生成一个唯一的键。shmget() 尝试使用这个键和指定的大小及权限创建一个新的共享内存段。如果成功,它会打印出共享内存段的标识符。

shmat

shmat() 函数是 Unix 和类 Unix 系统中 System V 共享内存 API 的一部分,用于将共享内存段附加到调用进程的地址空间中。这一步骤是在成功创建或获取共享内存段标识符后(通常通过 shmget() 完成)进行的。

函数原型

shmat() 的函数原型定义在 <sys/shm.h> 头文件中,具体如下:

void *shmat(int shmid, const void *shmaddr, int shmflg);
  • shmid: 共享内存段的标识符,这是通过 shmget() 获取的。
  • shmaddr: 指定共享内存附加到进程的地址空间中的具体地址。如果设置为 NULL,系统会自动选择一个合适的地址。如果非 NULL,则通常需要设置 shmflg 中的 SHM_RND 来使地址对齐到共享内存系统的要求。
  • shmflg: 操作标志,可以设置为 SHM_RDONLY 表示以只读方式附加共享内存。如果不需要特别的读写权限标志,则设置为 0
返回值
  • 成功: 返回一个指针,指向共享内存段在当前进程地址空间中的起始地址。
  • 失败: 返回 (void *) -1,并设置 errno 来指示错误原因。
错误处理

shmat() 可能会设置如下 errno 值:

  • EINVAL: shmid 无效,或 shmaddr 没有对齐。
  • EACCES: 调用进程没有适当的访问权限。
  • ENOMEM: 内存不足,无法完成操作。
示例用法

下面是一个示例,演示如何将共享内存段附加到进程的地址空间,并如何使用返回的地址:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>int main() {key_t key = ftok("somefile", 65);int shmid = shmget(key, 1024, 0644 | IPC_CREAT);if (shmid == -1) {perror("shmget failed");return 1;}char *data = (char *)shmat(shmid, NULL, 0);if (data == (void *) -1) {perror("shmat failed");return 1;}// 使用共享内存printf("Writing to shared memory...\n");sprintf(data, "Hello from process %d", getpid());// 分离共享内存if (shmdt(data) == -1) {perror("shmdt failed");return 1;}return 0;
}

在这个程序中:

  • ftok() 用于生成一个基于文件和项目编号的唯一键。
  • shmget() 创建一个新的共享内存段或获取已存在的共享内存段。
  • shmat() 将这个共享内存段附加到进程的地址空间,并返回一个指针。
  • 通过这个指针,我们向共享内存写入信息。
  • shmdt() 用于将共享内存从进程的地址空间中分离。

这个例子简单展示了如何通过 System V IPC 的共享内存机制进行进程间通信。

shmdt

shmdt() 是 Unix 和类 Unix 系统中 System V 共享内存 API 的一部分,用于将共享内存段从调用进程的地址空间中分离。这是在使用 shmat() 函数将共享内存附加到进程地址空间后的反向操作。

函数原型

shmdt() 的函数原型定义在 <sys/shm.h> 头文件中,其基本语法如下:

int shmdt(const void *shmaddr);
  • shmaddr: 这是指向共享内存段在进程地址空间中的起始地址的指针,这个地址是先前通过 shmat() 调用获取的。
返回值
  • 成功: 返回 0
  • 失败: 返回 -1 并设置 errno 来指示出错原因。
错误处理

调用 shmdt() 可能会设置以下 errno 值:

  • EINVAL: 指定的 shmaddr 无效,表示没有任何共享内存被附加到这个地址。
示例用法

这里是一个完整的示例,演示如何附加共享内存,使用它,然后将其从进程的地址空间中分离:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>int main() {key_t key = ftok("somefile", 65);int shmid = shmget(key, 1024, 0644 | IPC_CREAT);if (shmid == -1) {perror("shmget failed");return 1;}// 将共享内存附加到进程的地址空间char *data = (char *)shmat(shmid, NULL, 0);if (data == (void *) -1) {perror("shmat failed");return 1;}// 使用共享内存printf("Writing to shared memory...\n");sprintf(data, "Hello from process %d", getpid());// 操作完成后,从进程的地址空间中分离共享内存if (shmdt(data) == -1) {perror("shmdt failed");return 1;}return 0;
}

在这个例子中:

  • ftok() 生成一个键,用于 shmget()
  • shmget() 创建或获取共享内存。
  • shmat() 将共享内存附加到进程地址空间。
  • 使用指针 data 对共享内存进行操作。
  • shmdt() 将共享内存从进程地址空间分离,是进行清理的重要步骤,尤其是在长期运行的应用程序中,以避免资源泄漏。

shmdt() 是管理共享内存生命周期的关键部分,确保共享内存使用后能够正确地从进程中解除映射,以维护系统的健康和稳定。

shmctl

shmctl() 是 Unix 和类 Unix 系统中 System V 共享内存 API 的一部分,用于执行各种控制操作,如查询状态、设置权限、标记共享内存段的删除等。这个函数对于管理共享内存的生命周期和属性至关重要。

函数原型

shmctl() 的函数原型定义在 <sys/shm.h> 头文件中,具体如下:

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • shmid: 共享内存段的标识符,通过 shmget() 获取。
  • cmd: 指定要执行的命令。常用的命令包括 IPC_STATIPC_SETIPC_RMID 等。
  • buf: 指向 shmid_ds 结构的指针,该结构用于存储共享内存段的状态信息或修改共享内存段的权限和其他设置。
命令
  • IPC_STAT: 将共享内存段的当前信息复制到 buf 指向的 shmid_ds 结构中。
  • IPC_SET: 根据 buf 指向的 shmid_ds 结构中提供的信息设置共享内存段的参数。
  • IPC_RMID: 标记共享内存段以便删除。共享内存不会立即删除,而是等到所有附加的进程都已分离后才真正删除。
结构 shmid_ds

shmid_ds 结构包含了共享内存段的多种状态信息,包括权限、大小、最后访问时间等字段。具体字段可能根据不同的系统有所变化,但通常包括:

  • struct ipc_perm shm_perm: 控制权限,包括所有者、群组和其他的读写执行权限。
  • size_t shm_segsz: 共享内存段的大小,以字节为单位。
  • time_t shm_atime: 最后一次附加操作的时间。
  • time_t shm_dtime: 最后一次分离操作的时间。
  • time_t shm_ctime: 最后一次修改 ipc_perm 结构的时间。
  • pid_t shm_cpid: 创建共享内存段的进程ID。
  • pid_t shm_lpid: 最后操作共享内存段的进程ID。
  • unsigned short shm_nattch: 当前附加到共享内存段的进程数量。
示例用法

以下是一个使用 shmctl() 来删除共享内存段的例子:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>int main() {key_t key = ftok("somefile", 65);int shmid = shmget(key, 1024, 0644 | IPC_CREAT);if (shmid == -1) {perror("shmget failed");return 1;}// 标记共享内存段以便删除if (shmctl(shmid, IPC_RMID, NULL) == -1) {perror("shmctl failed");return 1;}printf("Shared memory segment marked for deletion\n");return 0;
}

在这个示例中:

  • ftok() 生成一个键,用于 shmget()
  • shmget() 创建共享内存。
  • shmctl() 使用 IPC_RMID 命令标记共享内存段以便删除。此操作不需要 shmid_ds 结构,因此第三个参数传递为 NULL

shmctl() 提供了对共享内存进行细粒度控制的能力,使得进程可以有效地管理和协调对共享资源的访问。

共享内存相关的函数
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);- 功能:创建一个新的共享内存段,或者获取一个既有的共享内存段的标识。新创建的内存段中的数据都会被初始化为0- 参数:- key : key_t类型是一个整形,通过这个找到或者创建一个共享内存。一般使用16进制表示,非0值- size: 共享内存的大小- shmflg: 属性- 访问权限- 附加属性:创建/判断共享内存是不是存在- 创建:IPC_CREAT- 判断共享内存是否存在: IPC_EXCL , 需要和IPC_CREAT一起使用IPC_CREAT | IPC_EXCL | 0664- 返回值:失败:-1 并设置错误号成功:>0 返回共享内存的引用的ID,后面操作共享内存都是通过这个值。void *shmat(int shmid, const void *shmaddr, int shmflg);- 功能:和当前的进程进行关联- 参数:- shmid : 共享内存的标识(ID),由shmget返回值获取- shmaddr: 申请的共享内存的起始地址,指定NULL,内核指定- shmflg : 对共享内存的操作- 读 : SHM_RDONLY, 必须要有读权限- 读写: 0- 返回值:成功:返回共享内存的首(起始)地址。  失败(void *) -1int shmdt(const void *shmaddr);- 功能:解除当前进程和共享内存的关联- 参数:shmaddr:共享内存的首地址- 返回值:成功 0, 失败 -1int shmctl(int shmid, int cmd, struct shmid_ds *buf);- 功能:对共享内存进行操作。删除共享内存,共享内存要删除才会消失,创建共享内存的进行被销毁了对共享内存是没有任何影响。- 参数:- shmid: 共享内存的ID- cmd : 要做的操作- IPC_STAT : 获取共享内存的当前的状态- IPC_SET : 设置共享内存的状态- IPC_RMID: 标记共享内存被销毁- buf:需要设置或者获取的共享内存的属性信息- IPC_STAT : buf存储数据- IPC_SET : buf中需要初始化数据,设置到内核中- IPC_RMID : 没有用,NULLkey_t ftok(const char *pathname, int proj_id);- 功能:根据指定的路径名,和int值,生成一个共享内存的key- 参数:- pathname:指定一个存在的路径/home/nowcoder/Linux/a.txt/ - proj_id: int类型的值,但是这系统调用只会使用其中的1个字节范围 : 0-255  一般指定一个字符 'a'问题1:操作系统如何知道一块共享内存被多少个进程关联?- 共享内存维护了一个结构体struct shmid_ds 这个结构体中有一个成员 shm_nattch- shm_nattach 记录了关联的进程个数问题2:可不可以对共享内存进行多次删除 shmctl- 可以的- 因为shmctl 标记删除共享内存,不是直接删除- 什么时候真正删除呢?当和共享内存关联的进程数为0的时候,就真正被删除- 当共享内存的key为0的时候,表示共享内存被标记删除了如果一个进程和共享内存取消关联,那么这个进程就不能继续操作这个共享内存。也不能进行关联。共享内存和内存映射的区别1.共享内存可以直接创建,内存映射需要磁盘文件(匿名映射除外)2.共享内存效果更高3.内存所有的进程操作的是同一块共享内存。内存映射,每个进程在自己的虚拟地址空间中有一个独立的内存。4.数据安全- 进程突然退出共享内存还存在内存映射区消失- 运行进程的电脑死机,宕机了数据存在在共享内存中,没有了内存映射区的数据 ,由于磁盘文件中的数据还在,所以内存映射区的数据还存在。5.生命周期- 内存映射区:进程退出,内存映射区销毁- 共享内存:进程退出,共享内存还在,标记删除(所有的关联的进程数为0),或者关机如果一个进程退出,会自动和共享内存进行取消关联。 

读写案例

write

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>int main() {    // 1.创建一个共享内存int shmid = shmget(100, 4096, IPC_CREAT|0664);printf("shmid : %d\n", shmid);// 2.和当前进程进行关联void * ptr = shmat(shmid, NULL, 0);char * str = "helloworld";// 3.写数据memcpy(ptr, str, strlen(str) + 1);printf("按任意键继续\n");getchar();// 4.解除关联shmdt(ptr);// 5.删除共享内存shmctl(shmid, IPC_RMID, NULL);return 0;
}

read

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>int main() {    // 1.获取一个共享内存int shmid = shmget(100, 0, IPC_CREAT);printf("shmid : %d\n", shmid);// 2.和当前进程进行关联void * ptr = shmat(shmid, NULL, 0);// 3.读数据printf("%s\n", (char *)ptr);printf("按任意键继续\n");getchar();// 4.解除关联shmdt(ptr);// 5.删除共享内存shmctl(shmid, IPC_RMID, NULL);return 0;
}
daic@daic:~/Linux/linuxwebserver/part02multiProgress/lesson27$ gcc read_shm.c -o read
daic@daic:~/Linux/linuxwebserver/part02multiProgress/lesson27$ gcc write_shm.c -o write
daic@daic:~/Linux/linuxwebserver/part02multiProgress/lesson27$ ls
read  read_shm.c  write  write_shm.c  共享内存.c
daic@daic:~/Linux/linuxwebserver/part02multiProgress/lesson27$ ./write 
shmid : 25
按任意键继续
daic@daic:~/Linux/linuxwebserver/part02multiProgress/lesson27$ ./read 
shmid : 25
helloworld
按任意键继续

共享内存操作命令

◼ ipcs 用法

 ipcs -a

// 打印当前系统中所有的进程间通信方式的信息

 ipcs -m

// 打印出使用共享内存进行进程间通信的信息

daic@daic:~/Linux$ ipcs -m------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 8          daic       600        134217728  2          dest         
0x00000000 11         daic       600        524288     2          dest         
0x00000000 14         daic       600        524288     2          dest         
0x00000000 15         daic       600        524288     2          dest         
0x00000000 18         daic       600        524288     2          dest         
0x00000000 19         daic       600        524288     2          dest         
0x00000000 20         daic       600        524288     2          dest         
0x00000064 26         daic       664        4096       2     

 ipcs -q

// 打印出使用消息队列进行进程间通信的信息

 ipcs -s

// 打印出使用信号进行进程间通信的信息

◼ ipcrm 用法

 ipcrm -M shmkey // 移除用shmkey创建的共享内存段

 ipcrm -m shmid

// 移除用shmid标识的共享内存段

 ipcrm -Q msgkey

// 移除用msqkey创建的消息队列

 ipcrm -q msqid

// 移除用msqid标识的消息队列

 ipcrm -S semkey

// 移除用semkey创建的信号

 ipcrm -s semid

// 移除用semid标识的信号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/8129.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ansible——INVENTORY主机清单

一、Inventory主机清单 Inventory支持对主机进行分组&#xff0c;每个组内可以定义多个主机&#xff0c;每个主机都可以定义在任何一个或多个主机组内 二、Inventory主机清单部署 2.1 前期准备 systemctl stop firewalld setenforce 0 yum install epel-release -y yum install…

【知识碎片】2024_05_07

今天记录了两个代码和C的几个破碎知识。 第一段代码是基础型的&#xff0c;关于数组。第二段代码是二分的&#xff0c;一开始没通过全部案例&#xff0c;值得再看。 每日代码 1.记负均正 输入一个数组&#xff0c;输出负数的个数&#xff0c;整数的平均值&#xff08;0都不参…

【JavaEE初阶系列】——Servlet运行原理以及Servlet API详解

目录 &#x1f6a9;Servlet运行原理 &#x1f6a9;Servlet API 详解 &#x1f393;HttpServlet核心方法 &#x1f393;HttpServletRequest核心方法 &#x1f388;核心方法的使用 &#x1f534;获取请求中的参数 &#x1f4bb;query string &#x1f4bb;直接通过form表…

Matlab图像中加入脉冲噪声、高斯噪声并用均值滤波、中值滤波进行滤波处理

一、脉冲噪声和高斯噪声简介 脉冲噪声和高斯噪声是两种常见的信号干扰类型&#xff0c;它们的特性和影响各不相同&#xff1a; 脉冲噪声&#xff08;Impulse Noise&#xff09;&#xff1a; 在图像中&#xff0c;脉冲噪声表现为随机出现的亮点或暗点&#xff0c;这些噪声点通常…

vector介绍与使用【C++】

C vector 前言一、vector的介绍c文档介绍简介 二、vector的定义和使用vector的定义vector代码演示 vector的使用vector iterator 的使用vector 空间增长问题vector 增删查改vector 迭代器失效问题引起底层空间改变eraseg与vs检测比较string迭代器失效 vector 在OJ中的使用只出现…

pandas 预处理

文章目录 第1关&#xff1a;数据读取与合并第2关&#xff1a;数据清洗第3关&#xff1a;数据转换 第1关&#xff1a;数据读取与合并 任务描述 本关任务&#xff1a;加载 csv 数据集&#xff0c;实现 DataFrame 合并。 知识讲解 Pandas 模块导入 import pandas as pd 读取 cs…

物流EDI:GEFCO EDI 需求分析

GEFCO专注于汽车物流领域近70年&#xff0c;是欧洲整车市场的物流供应商&#xff0c;也是欧洲十大领先的运输和物流集团之一。GEFCO的业务遍及六大洲&#xff0c;业务覆盖150个国家&#xff0c;在全球拥有庞大的员工队伍&#xff0c;在全球汽车行业的挑战中茁壮成长。为汽车制造…

WordPress插件:链接自动识别转为超链接

WordPress插件&#xff1a;链接自动识别转为超链接 <?phpfunction open_links_in_new_tab() {add_filter(the_content, make_clickable);function autoblank($text) {$return str_replace(<a, <a target"_blank", $text);return $return;}add_filter(th…

[Scrcpy]数据线连接安卓手机投屏windows电脑[win控制安卓手机]比Samsung Dex好用

配置好&#xff0c;只需要两步即可完成安卓手机投屏windows 第一步&#xff1a;usb线连接windows电脑 第二步&#xff1a;cmd输入投屏命令srccpy 搞定 前言/背景 一些视频资料只能下载到手机&#xff0c;很不喜欢手机那么小屏幕播放&#xff0c;播放很不方便 在家的话可以投…

如何看待2024数维杯?

一、赛事介绍 美赛结束后,2024年又一场高含金量数模竞赛开始报名啦!数维杯每年上半年为数维杯国赛(5月,俗称小国赛),下半年为数维杯国际赛(11月),累计参赛高校千余所,参赛人数超14万人,经过八年多的发展,已成为继数学建模国赛和美赛之后的第三大全国性数学建模赛事,…

phpstudy靶场访问显示404 Not Found

涉及靶场 upload-labd sqli-labs pikachu dvwa 以及所有部署在phpstudy中的靶场 一、检查phpstduy设置 localhost——管理——修改 1、根目录&#xff08;默认设置&#xff0c;不要改&#xff09; localhost这个域名必须保留&#xff0c;并且把根目录设置为phpstudy的WWW文…

mysql优化(慢查询,索引,表结构)

从慢查询优化,索引优化和表结构三个方面入手,进行总结: 慢查询优化 启用慢查询日志&#xff1a;开启慢查询日志&#xff0c;记录执行时间超过阈值的SQL语句&#xff0c;以便后续分析。分析慢查询日志&#xff1a;使用工具&#xff08;如mysqldumpslow&#xff09;或直接查看日…

如何利用AI提高内容生产效率?

要通过AI技术提升内容生产的效率和质量&#xff0c;可以从以下几个方面进行探讨&#xff1a; 1. 自动化内容生成 AI技术可以快速生成大量高质量的文本、图像和音频内容。例如&#xff0c;利用自然语言处理&#xff08;NLP&#xff09;技术&#xff0c;AI可以自动生成新闻报道…

CSS-背景属性

目录 背景属性 background-color (背景颜色 ) background-image (背景图片 ) background-repeat (背景图平铺方式 ) no-repeat 不平铺 repeat-x 水平方向平铺 repeat-y 垂直方向平铺 repeat 平铺 background-position (背景图位置) background-size (背景缩…

第80天:WAF 攻防-漏洞利用HPP 污染分块传输垃圾数据

案例一&#xff1a;安全狗-SQL 注入-知识点 正常访问会被拦截 like绕过 对比成功&#xff0c;正常返回 对比失败&#xff0c;不返回 post绕过 这里需要支持post注入。这里是我自己改的REQUEST 这里其实安全狗可以开启post验证&#xff0c;看别人知不知道能开启了 过滤了 模拟…

如何备考PMP才能一次通过?

PMP备考一个月就能通过&#xff0c;培训机构中就应该这么学&#xff01; PMP考试的难度其实并没有大家想象中的那么大&#xff0c;现在培训机构的通过率基本也在90%以上&#xff0c;而这90%以上也基本都是头一次参加考试很少有参加重考的学员。我就是在威班PMP培训了一个多月一…

如何使用低代码快速创建一个复杂交叉报表?

前言 在当今数字化时代&#xff0c;数据是企业决策和发展的重要支柱。为了更好地理解和利用数据&#xff0c;生成清晰、全面的报表至关重要。而复杂交叉报表作为一种高级数据分析工具&#xff0c;能够帮助企业深入挖掘数据背后的价值&#xff0c;提供全面的数据概览和分析结果…

Python 正则表达式 *, + 和 ? 符号

Python 正则表达式 *, 和 ? 符号 引言正文* 符号 符号? 符号 引言 这里简单说明一下 Python 正则表达式中的 *, 和 ? 符号。 正文 * 符号 对它前面的正则式匹配 0 到任意次重复&#xff0c; 尽量多的匹配字符串。 ab* 会匹配 a&#xff0c;ab&#xff0c;或者 a 后面跟…

联发科技发布天玑9300+旗舰5G生成式AI芯片 | 最新快讯

5 月 7 日消息&#xff0c;联发科技今天举办了天玑开发者大会 2024。大会上&#xff0c;联发科技开启了“天玑 AI 先锋计划”&#xff0c;联合业界生态企业发布了《生成式 AI 手机产业白皮书》&#xff0c;分享了生成式 AI 端侧部署的解决方案“天玑 AI 开发套件”。同时&#…

大数据技术原理与技术简答

1、HDFS中名称节点的启动过程 名称节点在启动时&#xff0c;会将FsImage 的内容加载到内存当中&#xff0c;此时fsimage是上上次关机时的状态。然后执行 EditLog 文件中的各项操作&#xff0c;使内存中的元数据保持最新。接着创建一个新的FsImage 文件和一个空的 Editlog 文件…