赞
踩
shm_xx系列函数是用于操作共享内存的一组函数,它们通常包括shmget、shmctl、shmat和shmdt。下面对这些函数进行详细解释:
int shmget(key_t key, size_t size, int shmflg)
key
:用于识别共享内存段的键值,通常使用 ftok
函数生成。size
:共享内存段的大小。单位是字节。shmflg
:打开标志,用于指定操作的方式,比如创建共享内存段、获取共享内存标识符等。shmget
函数是用于创建共享内存段、获取共享内存标识符或者访问一个已存在的共享内存段的函数,其声明如下: shmget
函数的主要功能包括:
key
对应的共享内存段不存在,并且设置了创建标志(IPC_CREAT
),则会创建一个新的共享内存段,大小为 size
字节。key
对应的共享内存段存在,则会返回共享内存标识符。IPC_CREAT
标志。此时若指定的 key
对应的共享内存段不存在,shmget
函数将会返回错误。 shmget
函数的返回值是共享内存标识符(shmid),用于后续对共享内存段的访问操作,比如连接共享内存、获得共享内存的地址等。
在使用 shmget
函数时,需要注意确保对共享内存的大小和权限的设置,避免潜在的问题,比如内存溢出或者权限不足等。同时,需要根据具体需求合理设置 shmflg
参数,确保对共享内存的访问操作符合预期。
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
shmid
:是共享内存标识符,是由 shmget
函数返回的。cmd
:是控制命令,用于指定对共享内存的具体操作,比如删除共享内存段、获取共享内存信息等。buf
:是指向 shmid_ds
结构体的指针,用于传递或者获取共享内存的信息。shmctl
函数是用于控制共享内存段的操作函数,主要用于对共享内存段进行控制操作,比如删除、获取信息等,其声明如下:shmctl
函数的主要功能包括:
cmd
参数可以取以下值之一:
IPC_STAT
:获取共享内存的状态信息,并将其存储在 buf
指向的结构体中。IPC_SET
:设置共享内存的状态信息,更新共享内存的权限等。IPC_RMID
:删除共享内存段,释放资源。 需要注意的是,在使用 shmctl
函数时,要根据具体需求选择合适的控制命令,并确保传入正确的参数,以免出现意外的错误。同时,删除共享内存段时,需要注意确保所有关联进程已经分离了共享内存段,否则删除操作可能会失败。
void *shmat(int shmid, const void *shmaddr, int shmflg)
shmid
:是共享内存标识符,是由 shmget
函数返回的。shmaddr
:是一个指针,用于指定将共享内存段映射到进程地址空间的地址,通常设为 NULL
。shmflg
:参数用于指定连接共享内存段的标志,通常可以设置为 0。 shmat
函数的主要作用是将共享内存段连接到当前进程的地址空间,实现进程对共享内存段的访问。连接成功后,shmat
函数将返回一个指向共享内存段起始地址的指针,进程可以通过该指针来访问共享内存段中的数据。
一般情况下,shmaddr
参数设为 NULL
,由系统自动选择合适的地址来映射共享内存段到进程地址空间中。shmflg
参数通常设为 0,表示默认的连接标志,除非有特殊需求,一般不需要修改。
需要注意的是,在使用 shmat
函数时,要确保传入正确的共享内存标识符 shmid
,避免出现连接错误。另外,在使用完共享内存后,要及时调用 shmdt
函数将共享内存段从当前进程地址空间中分离,避免资源泄漏。
int shmdt(const void *shmaddr)
shmaddr
:是共享内存段连接到进程地址空间的起始地址,通常是由 shmat
函数返回的。 shmdt
函数的主要作用是断开当前进程与共享内存段的连接,使得进程无法再访问共享内存段中的数据。调用 shmdt
函数后,共享内存段仍然存在,但当前进程无法再对其进行操作。
在使用 shmdt
函数时,需要传入正确的共享内存段起始地址 shmaddr
,确保将正确的共享内存段从当前进程中分离。另外,需要注意的是,分离共享内存段后,如果没有其他进程仍然连接着该共享内存段,系统会释放该共享内存段,从而释放相关资源。
在使用共享内存时,需要注意合理地管理共享内存的连接和分离,避免出现资源泄漏或者错误的操作。
ftok
函数是一个用于生成一个 System V IPC(Inter-Process Communication,进程间通信)键值的函数,其声明如下:
key_t ftok(const char *pathname, int proj_id);
pathname
参数是一个指向字符串的指针,用于指定一个已经存在的文件的路径名。proj_id
参数是一个用户定义的整数,可以是 0 到 255 的范围内的任意值。 ftok
函数会根据指定的 pathname
和 proj_id
生成一个唯一的键值,用于创建或访问 System V IPC 的资源,如共享内存、信号量和消息队列。
实际上,ftok
函数根据 pathname
参数对应文件的 inode 号和 proj_id
参数生成一个 32 位的键值,最高 8 位存放 proj_id
,低 24 位存放 pathname
对应文件的 inode 号的后 24 位。这样可以保证相同的 pathname
和 proj_id
参数生成相同的键值。
需要注意的是,在使用 ftok
函数时要确保 pathname
参数是一个已经存在的文件的路径名,否则会导致生成的键值不唯一。另外,proj_id
参数的取值范围是 0 到 255,超出这个范围可能导致键值重复。
综上所述,ftok
函数是用于生成 System V IPC 键值的一个实用工具函数,可以通过指定文件路径和项目标识来确保生成唯一的键值,用于进程间通信的各种资源的创建和访问。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #define SHM_SIZE 1024 // 共享内存大小 int main() { key_t key = ftok("shmfile", 'R'); // 创建共享内存的键值 int shmid; // 创建共享内存段 shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666); if (shmid == -1) { perror("shmget"); exit(1); } // 连接共享内存段 char *shmaddr = (char *)shmat(shmid, NULL, 0); if (shmaddr == (char *)-1) { perror("shmat"); exit(1); } // 写入数据到共享内存 strcpy(shmaddr, "Hello, Shared Memory!"); printf("Data written to shared memory: %s\n", shmaddr); // 分离共享内存段 if (shmdt(shmaddr) == -1) { perror("shmdt"); exit(1); } // 删除共享内存段 if (shmctl(shmid, IPC_RMID, 0) == -1) { perror("shmctl"); exit(1); } return 0; }
shm_open
是 POSIX 标准中定义的用于创建或打开共享内存对象的函数。与传统的 shmget
函数类似,shm_open
提供了一种不同的方式来管理共享内存,使用文件描述符来标识共享内存对象。shm_open
的原型如下:
int shm_open(const char *name, int oflag, mode_t mode);
name
参数是一个指向表示共享内存对象名称的字符串的指针。共享内存对象通过名称在文件系统中标识。oflag
参数指定了打开共享内存对象时的操作标志,可以是一组位或运算的标志,比如 O_CREAT
(创建共享内存对象), O_RDWR
(可读写方式打开)等。mode
参数指定了新创建的共享内存对象的权限标志,通常与 open
系统调用中使用的 mode
参数一样。 使用 shm_open
函数创建或打开共享内存对象后,可以通过标准的文件 I/O 函数(如 read
和 write
)对共享内存进行读写操作。共享内存对象在文件系统中以名字为标识,不同进程可以通过相同的名字打开同一个共享内存对象,从而实现进程间通信。
在使用 shm_open
函数时,需要注意以下几点:
shm_unlink
函数来释放该共享内存对象,以防止资源泄漏。 总的来说,shm_open
提供了一种基于文件描述符的共享内存对象管理方式,使得共享内存在不同进程之间的使用更加灵活和方便。
shm_unlink
是一个函数,用于删除由 shm_open
创建的共享内存对象的名称。在 POSIX 标准中,共享内存对象在文件系统中以名称标识,使用 shm_open
打开该共享内存对象后,可以通过 shm_unlink
函数删除该对象的名字,但不会立即释放共享内存本身。只有在所有进程都关闭该共享内存对象的文件描述符或调用 shm_unlink
之后,共享内存对象才会被彻底删除。shm_unlink
的原型如下:
int shm_unlink(const char *name);
name
参数是一个指向表示要删除的共享内存对象名称的字符串的指针。 使用 shm_unlink
函数可以确保在不再需要共享内存对象时清理对象的名称,这样可以避免其他进程再次通过该名称打开共享内存对象。但需要注意的是,即使调用了 shm_unlink
,只有当所有打开该共享内存对象的文件描述符都关闭,共享内存对象才会被系统真正删除。
一般来说,在不再需要使用共享内存对象时,建议及时调用 shm_unlink
,以便及时释放已不需要的资源。这样可以更好地管理共享内存,避免资源泄漏和冗余共享内存对象的存在。
以下是一个简单的示例代码,展示了如何使用 shm_open
和 shm_unlink
函数来创建和删除共享内存对象的名称。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #define SHM_NAME "/my_shared_memory" #define SHM_SIZE 1024 int main() { const char *data = "Hello, this is shared memory demo!"; // Create or open a shared memory object int shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); ftruncate(shm_fd, SHM_SIZE); // Map the shared memory object into memory char *shm_ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); // Write data to the shared memory strcpy(shm_ptr, data); printf("Data written to shared memory: %s\n", shm_ptr); // Unmap the shared memory munmap(shm_ptr, SHM_SIZE); // Close the shared memory object close(shm_fd); // Unlink the shared memory object name shm_unlink(SHM_NAME); return 0; }
在这个示例代码中,首先使用 shm_open
函数创建或打开一个共享内存对象,并指定名称为 "/my_shared_memory"
。然后使用 ftruncate
函数设置共享内存对象的大小为 SHM_SIZE
字节。
接着,使用 mmap
函数将共享内存对象映射到当前进程的内存空间中,使得可以对其进行读写操作。将数据写入共享内存后,通过 munmap
函数解除共享内存的映射,并通过 close
函数关闭共享内存对象的文件描述符。
最后,调用 shm_unlink
函数删除共享内存的名称,这样其他进程就无法再使用该名称打开共享内存对象。
推荐阅读:进程间通信–共享内存篇
欢迎大家指导和交流!如果我有任何错误或遗漏,请立即指正,我愿意学习改进。期待与大家一起进步!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。