长沙网站制作收费明细,网站建设个人简历表达,网站登陆系统怎么做,东莞网站制作品牌祥奔科技目录
共享内存
shmget()#xff1a;创建或获取共享内存
shmat()#xff1a;映射
shmdt()#xff1a;解除映射
shmctl()#xff1a;获取或设置属性
sem.h文件
sem.c文件
shm.c文件
Makefile文件
执行过程 共享内存 共享内存#xff1a;将内存进行共享#xff0c…目录
共享内存
shmget()创建或获取共享内存
shmat()映射
shmdt()解除映射
shmctl()获取或设置属性
sem.h文件
sem.c文件
shm.c文件
Makefile文件
执行过程 共享内存 共享内存将内存进行共享它允许多个不相关的进程访问同一个逻辑内存直接将一块裸露的内存放在需要数据传输的进程前供进程使用。 因此共享内存是效率最高的一种IPC通信机制可以在多个进程间共享和传递数据进程间需要共享的数据被放在共享内存区域所有需要访问该共享内存的进程都要把该共享区域映射到本进程的地址空间中因此所有进程都可访问共享内存的地址。 但是共享内存需要进程自己去维护如同步、互斥等。如进程1在读取共享内存的数据时进程2却修改了共享内存的数据这会导致数据混乱。因此共享内存属于临界资源在某一时刻只能有一个进程对其操作读写。共享内存一般不能单独使用而是配合信号量、互斥锁等协调机制让各个进程在高效交换数据时不会发生数据践踏、破坏等行为。 共享内存思想进程间虚拟内存空间本来相互独立不能相互访问但是可以通过某种方式使得相同的一块物理内存多次映射到不同的进程虚拟空间中相当于多个进程的虚拟内存空间部分重叠在一起。共享内存少了拷贝的操作减少了系统开销因此效率极高。 shmget()创建或获取共享内存 shmget()函数会创建或获取一个共享内存对象并返回共享内存标识符。 #include sys/ipc.h
#include sys/shm.h
int shmget(key_t key, size_t size, int shmflg);
/*
key共享内存的标识符IPC_PRIVATE创建一块新的共享内存0当shmflg参数设置了IPC_PRIVATE标志则将创建一块新的共享内存大于0的32位整数根据shmflg参数来确定操作
size要创建共享内存的大小所有的内存分配操作都是以页为单位的所有即使只申请一个字节的内存内存也会分配一页。
shmflg表示创建的共享内存的模式标志参数。标志 | modeIPC_CREAT如果内核中不存在关键字与key相等的共享内存则新建一个共享内存如果存在则返回此共享内存的标识符。IPC_EXCL如果内核中不存在关键字与key相等的共享内存则新建一个共享内存如果存在则报错SHM_HUGETLB使用“大页面”来分配共享内存所谓的“大页面”指的是内核为了提高程序性能对内存实行分页管理时采用比默认尺寸4KB更大的分页以减少缺页中断。 Linux 内核支持以 2MB 作为物理页面分页的基本单位。SHM_NORESERVE不在交换分区中为这块共享内存保留空间。
返回值共享内存的ID。
*/ 当调用shmget()函数失败时将产生错误代码 EACCES指定的消息队列已存在但调用进程没有权限访问它 EEXISTkey指定的消息队列已存在而msgflg中同时指定IPC_CREAT和IPC_EXCL标志 EINVAL创建共享内存是参数size小于SHMMIN或大于SHMMAX ENFILE已达到系统范围内打开文件总数的限制 ENOENT给定的key不存在任何共享内存并且未指定IPC_CREAT ENOMEM内存不足无法为共享内存分配内存 shmat()映射 shmat()函数是把共享内存区域对象映射到调用进程的地址空间。 #include sys/types.h
#include sys/shm.h
void *shmat(int shmid, const void *shmaddr, int shmflg);
/*
shmid共享内存ID
shmaddr如果不为NULL则系统会根据shmaddr来选择一个合适的内存区域如果为NULL则系统会自动选择一个合适的虚拟内存空间地址去映射共享内存
shmflgSHM_RDONLY以只读方式映射共享内存SHM_REMAP重新映射此时shmaddr不能为NULLNULLSHM自动选择比shmaddr小的最大页对齐地址
返回值共享内存的起始地址。
*/ 共享内存的映射需注意 共享内存只能以只读或可读写方式映射无法以只写方式映射。 shmaddr参数一般设置为NULL让系统自动地寻找合适的地址。当不为NULL时SHMFLG必须设置为SHM_RND系统将会选择比shmaddr小而又最大的页对齐地址即为SHMLBA的整数倍作为共享内存区域的起始地址。如果没有设置SHM_RND那么shmaddr必须是严格的页对齐地址。 shmdt()解除映射 shmdt()函数是解除进程和共享内存间的映射。 #include sys/types.h
#include sys/shm.h
void shmdt(const void *shmaddr);
/*
shmaddr映射的共享内存的起始地址
返回值执行成功0执行失败-1并将错误原因存于errno
*/ 注意该函数并不删除所指定的共享内存区而只是将先前用shmat()函数映射好的共享内存脱离当前进程共享内存还是存在于物理内存中。 shmctl()获取或设置属性 shmctl()函数用于获取或设置共享内存的相关属性。 #include sys/ipc.h
#include sys/shm.h
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
/*
shmid共享内存标识符
cmdIPC_STAT获取属性信息放置到 buf 中。IPC_SET设置属性信息为 buf 指向的内容。IPC_RMID删除该共享内存。IPC_INFO获得关于共享内存的系统限制值信息。SHM_INFO获得系统为共享内存消耗的资源信息。SHM_STAT与 IPC_STAT 具有相同的功能但 shmid 为该 SHM 在内核中记录所有 SHM 信息的数组的下标因此通过迭代所有的下标可以获得系统中所有 SHM 的相关信息。SHM_LOCK禁止系统将该 SHM 交换至 swap 分区。SHM_UNLOCK允许系统将该 SHM 交换至 swap 分区。
buf共享内存属性信息结构体指针设置或者获取信息都通过该结构体
*/ 一个SHM被交换至swap分区后如果被设置了SHM_LOCK那么任何访问这个SHM的进程都将会遇到页错误。进程可以通过IPC_STAT后得到的mode来检测SHM_LOCKED信息。 struct shmid_ds {struct ipc_perm shm_perm; /* 所有权和权限 */size_t shm_segsz; /* 共享内存尺寸字节 */time_t shm_atime; /* 最后一次映射时间 */time_t shm_dtime; /* 最后一个解除映射时间 */time_t shm_ctime; /* 最后一次状态修改时间 */pid_t shm_cpid; /* 创建者 PID */pid_t shm_lpid; /* 后一次映射或解除映射者 PID */shmatt_t shm_nattch; /* 映射该 SHM 的进程个数 */...
};struct ipc_perm {key_t __key; /* 该共享内存的键值 key */uid_t uid; /* 所有者的有效 UID */gid_t gid; /* 所有者的有效 GID */uid_t cuid; /* 创建者的有效 UID */gid_t cgid; /* 创建者的有效 GID */unsigned short mode; /* 读写权限 SHM_DEST SHM_LOCKED 标记 */unsigned short __seq; /* 序列号 */
}; sem.h文件
#ifndef __SEM_H
#define __SEM_H#include sys/types.h
#include sys/ipc.h
#include sys/sem.h
#include sys/wait.h
#include unistd.h
#include fcntl.h
#include stdlib.h
#include stdio.h
#include string.h
#include limits.h
#include errno.hint init_sem(int sem_id, int init_value);
int del_sem(int sem_id);
int sem_p(int sem_id);
int sem_v(int sem_id);#endif sem.c文件
#include sys/types.h
#include sys/ipc.h
#include sys/sem.h
#include sys/wait.h
#include unistd.h
#include fcntl.h
#include stdlib.h
#include stdio.h
#include string.h
#include limits.h
#include errno.hunion semun
{int val; //供semctl()函数cmd SETVAL时使用struct semid_ds *buf; //供semctl()汉斯cmd IPC_STAT|IPC_SET时使用
};/* 初始化信号量 */
int init_sem(int sem_id, int init_value)
{union semun sem_union;sem_union.val init_value;/* 信号量ID信号量编号命令联合体 */if( semctl( sem_id, 0, SETVAL, sem_union) -1 ){printf(Initialize semaphore error!\n);return -1;}else{printf(Initialize semaphore!\n);}
}/* 删除信号量 */
int del_sem(int sem_id)
{union semun sem_union;/* 信号量ID信号量编号命令联合体 */if( semctl( sem_id, 0, IPC_RMID, sem_union) -1 ){printf(Delete semaphore error!\n);return -1;}else{printf(Delete semaphore!\n);}
}/* p操作 */
int sem_p(int sem_id)
{struct sembuf sops;sops.sem_num 0; //信号量的编号0nsems-1sops.sem_op -1; //表示p操作sops.sem_flg SEM_UNDO; //系统自动释放在系统中残留的信号量/* 信号量ID结构体信号量数量 */if( semop( sem_id, sops, 1) -1 ){perror(p operation error!\n);return -1;}else{printf(p operation successful!\n);return 0;}
}/* v操作 */
int sem_v(int sem_id)
{struct sembuf sops;sops.sem_num 0; //信号量的编号0nsems-1sops.sem_op 1; //表示v操作sops.sem_flg SEM_UNDO; //系统自动释放在系统中残留的信号量/* 信号量ID结构体信号量数量 */if( semop( sem_id, sops, 1) -1 ){perror(v operation error!\n);return -1;}else{printf(v operation successful!\n);return 0;}
} shm.c文件
#include sys/types.h
#include sys/ipc.h
#include sys/sem.h
#include sys/shm.h
#include sys/stat.h
#include unistd.h
#include fcntl.h
#include stdlib.h
#include stdio.h
#include string.h
#include errno.h
#include sem.hint main(int argc, char** argv)
{int sem_id, shm_id;char *addr;pid_t pid;/* 创建信号量键值数量模式 */sem_id semget((key_t)0x1100, 1, IPC_CREAT|0666);/* 创建共享内存键值共享内存大小模式 */shm_id shmget((key_t)0x1111, 1024, IPC_CREAT|0666);/* 初始化信号量 */init_sem(sem_id, 0);if( ( pid fork() ) -1){perror(rork error!\n);}else if(pid 0) //子进程{printf(Child process will wait for some seconds...\n);sleep(3);/* 映射共享内存映射地址系统自动分配 */if( ( addr shmat(shm_id, NULL, 0) ) (void *)-1 ){printf(child shmat error!\n);exit(-1);}memcpy(addr, hello couvrir, 14);printf(the child process is running...\n);sem_v(sem_id);}else //父进程{sem_p(sem_id);printf(the father process is running...\n);/* 映射共享内存映射地址系统自动分配 */if( ( addr shmat(shm_id, NULL, 0) ) (void *)-1 ){printf(father shmat error!\n);exit(-1);}printf(share memory string:%s\n, addr);/*解除共享内存映射*/shmdt(addr);sem_v(sem_id);del_sem(sem_id);}exit(0);
} Makefile文件
照旧 执行过程