Linux 基础入门操作 第九章 进程之间通讯共享内存
9.4 共享内存
速度最快,效率最高的进程间通信方式,进程之间直接访问内存,而不是通过传送数据。但是使用共享内存需要自己提供同步机制。
9.4.1 创建函数
int shmget(key_t key, size_t size, int shmflg);
第一个参数,与信号量的 semget 函数一样,程序需要提供一个参数 key(非 0 整数),它有效地为共享内存段命名,shmget 函数成功时返回一个与 key 相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1。
不相关的进程可以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调用 shmget 函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget 函数的返回值),只有 shmget 函数才直接使用信号量键,所有其他的信号量函数使用由semget 函数返回的信号量标识符。
第二个参数,size 以字节为单位指定需要共享的内存容量
第三个参数,shmflg 是权限标志,它的作用与 open 函数的 mode 参数一样,如果要想在 key 标识的共享内存不存在时,创建它的话,可以与 IPC_CREAT 做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。
9.4.2 启动函数
第一次创建完共享内存时,它还不能被任何进程访问,shmat 函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
void *shmat(int shm_id, const void *shm_addr, int shmflg);
第一个参数,shm_id 是由 shmget 函数返回的共享内存标识。
第二个参数,shm_addr 指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共
享内存的地址。
第三个参数,shm_flg 是一组标志位,通常为 0。
调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1
9.4.3 分离函数
该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。
int shmdt(const void *shmaddr);
参数 shmaddr 是 shmat 函数返回的地址指针,调用成功时返回 0,失败时返回-1.
9.4.4 控制函数
与信号量的 semctl 函数一样,用来控制共享内存,它的原型如下:
int shmctl(int shm_id, int command, struct shmid_ds *buf);
第一个参数,shm_id 是 shmget 函数返回的共享内存标识符。
第二个参数,command 是要采取的操作,它可以取下面的三个值:
IPC_STAT:把 shmid_ds 结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖 shmid_ds 的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为 shmid_ds 结构中给出的值
IPC_RMID:删除共享内存段
第三个参数,buf 是一个结构指针,它指向共享内存模式和访问权限的结构
shmid_ds 结构至少包括以下成员:
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
9.4.5 案例
使用 shmget()函数创建一个共享内存区域,在这个共享内存区域中写入字符串”welcome to mrdoft“,然后在父子进程中分别读取共享内存中的数据,进而实现进程间的数据交换。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
int main()
{
int shmid;
int proj_id;
key_t key;
int size;
char *addr;
pid_t pid;
key = IPC_PRIVATE;
shmid = shmget(key,1024,IPC_CREAT|0660);//创建共享内存,返回共享内存区域的标识符
if(shmid == -1){
perror("create share memory failed!");
return 1;
}
addr = (char *)shmat(shmid,NULL,0); //获得共享内存的地址
if(addr == (char *)(-1)){
printf("cannot attach %s\n",strerror(errno));
return 1;
}
printf("share memory segment's address:%p\n",addr);//打印共享内存地址
strcpy(addr,"welcome to mrsoft"); //复制字符串到共享内存
pid = fork(); //创建子进程
if(pid == -1){
perror("error");
return 1;
}
else if(pid == 0){
printf("child process string is' %s'\n",addr); //子进程读取共享内存的内容
_exit(0);
}
else{
wait(NULL);
printf("parent process string is '%s'\n",addr); //父进程读取共享内存的内容
if(shmdt(addr) == -1){ //分离共享内存区域
perror("release failed\n");
return 1;
}
if(shmctl(shmid,IPC_RMID,NULL) == -1){ //删除共享内存区域
perror("failed");
return 1;
}
}
}
原文地址:https://blog.csdn.net/huanghongqi11/article/details/142369222
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!