网站上线后所要做的事情,广州外贸网站推广,wordpress 仿f,乐清建设公司网站5 共享内存
共享内存允许两个或多个进程访问给定的同一块存储区域。它是效率最高的一种进程通信方式#xff0c;节省了不同进程间多次读写的时间#xff1b;在写进程的操作尚未完成时#xff0c;不应有进程从共享内存中读取数据。共享内存自身不限制对共享内存的读写次序节省了不同进程间多次读写的时间在写进程的操作尚未完成时不应有进程从共享内存中读取数据。共享内存自身不限制对共享内存的读写次序程序开发人员应自觉遵循读写规则一般情况下共享内存与信号量一起使用由信号量帮它实现读写操作的同步Linux提供了如下系统调用来实现共享内存的申请、管理与释放 – shmget – shmat – shmdt – shmctl
5.1 shmget函数
#include sys/shm.hint shmget(key_t key, size_t size, int shmflg);功能创建一个新的共享内存或打开一块已存在的共享内存。
参数说明
key传入参数共享内存的键值通常为一个整数size设置共享内存的大小shmflg设置shmget函数的创建条件一般设置为IPC_CREAT或IPC_EXCL及进程对共享内存的读写权限。
返回值说明
成功返回共享内存的标识符一个非负整数不成功返回-1并设置errno。
5.2 shmat函数
#include sys/shm.hvoid *shmat(int shmid, const void *shmaddr, int shmflg);功能进行地址映射将共享内存映射到进程虚拟地址空间中。
参数说明
shmid共享内标识符通常为shmget函数的返回值shmaddr指针类型的传入参数用于指定共享内存映射到虚拟内存时的虚拟地址设置为NULL时映射地址由系统决定shmflg设置共享内存的使用方式如果shmflg SHM_RDONLY则共享内存将以只读的方式进行映射当前进程只能从共享内存中读取数据。
返回值说明
成功返回映射的地址并更改共享内存shmid_ds结构中的属性信息不成功返回-1并设置errno。
5.3 shmdt函数
#include sys/shm.hint shmdt(const void *shmaddr);功能解除物理内存与进程虚拟地址空间的映射关系。
参数说明
shmaddrshmat函数返回的虚拟空间地址。
返回值说明
成功返回映射的地址并更改共享内存shmid_ds结构中的属性信息不成功返回-1并设置errno。
5.4 shmctl函数
#include sys/shm.hint shmctl(int shmid, int cmd, struct shmid_ds *buf);
//为了方便对共享内存进行管理由内核维护的存储共享内存属性信息的结构体
struct shmid_ds{struct ipc_perm shm_perm; /* 操作权限*/size_t shm_segsz; /*段的大小以字节为单位*/time_t shm_atime; /*最后一个进程附加到该段的时间*/time_t shm_dtime; /*最后一个进程离开该段的时间*/time_t shm_ctime; /*最后一个进程修改该段的时间*/unsigned short shm_cpid; /*创建该段进程的pid*/unsigned short shm_lpid; /*在该段上操作的最后1个进程的pid*/short shm_nattch; /*当前附加到该段的进程的个数*//*下面是私有的*/unsigned short shm_npages; /*段的大小以页为单位*/unsigned long *shm_pages; /*指向frames-SHMMAX的指针数组*/struct vm_area_struct *attaches; /*对共享段的描述*/
};
功能对已存在的共享内存进行操作具体的操作由参数确定。
参数说明
shmid共享内存标识符cmd要执行的操作常用的设置为IPC_RMID功能为删除共享内存buf对共享内存的管理信息进行设置该参数是结构体shmid_ds的指针。
返回值说明
成功返回0不成功返回-1并设置errno。
特殊说明
共享内存与消息队列、信号量相同在使用完毕后都应该进行释放调用fork函数创建子进程时子进程会继承父进程已绑定的共享内存当调用exec函数更改子进程功能及调用exit函数时子进程都会解除与共享内存的映射关系因此在必要时仍应使用shmctl函数对共享内存进行删除。
【案例1】使用共享内存机制实现两个进程间的通信。
shm_w.c
#include stdio.h
#include sys/ipc.h
#include sys/shm.h
#include sys/types.h
#include unistd.h
#include string.h
#define SEGSIZE 4096 //定义共享内存容量
typedef struct{ //读写数据结构体char name[8];int age;
} Stu;
int main() {int tempShmId, i;key_t tempKey;char tempName[8];Stu *tempSmap;/*ftok函数的作用系统建立IPC通讯如消息队列、共享内存时必须指定一个ID值。通常情况下该id值通过ftok函数得到。*/tempKey ftok(/, 0); //获取关键字if (tempKey -1) {perror(ftok error);return -1;}//of ifprintf(key%d\n, tempKey);//创建共享内存tempShmId shmget(tempKey, SEGSIZE, IPC_CREAT | IPC_EXCL | 0664);if (tempShmId -1) {perror(create shared memory error\n);return -1;}//of ifprintf(shm_id%d\n, tempShmId);tempSmap (Stu*)shmat(tempShmId, NULL, 0); //将进程与共享内存绑定memset(tempName, 0x00, sizeof(tempName));strcpy(tempName, Jhon);tempName[4] 0;for (i 0; i 3; i){ //写数据tempName[4] 1;strncpy((tempSmap i)-name, tempName, 5);(tempSmap i)-age 20 i;}//of for iif (shmdt(tempSmap) -1){ //解除绑定perror(detach error);return -1;}//of ifreturn 0;
}//of mainshm_r.c
#include stdio.h
#include string.h
#include sys/ipc.h
#include sys/shm.h
#include sys/types.h
#include unistd.h
typedef struct{char name[8];int age;
} Stu;
int main() {int tempShmId, i;key_t tempKey;Stu *tempSmap;struct shmid_ds tempBuf;tempKey ftok(/, 0); //获取关键字if (tempKey -1) {perror(ftok error);return -1;}//of ifprintf(key%d\n, tempKey);tempShmId shmget(tempKey, 0, 0); //创建共享内存if (tempShmId -1) {perror(shmget error);return -1;}//of ifprintf(shm_id%d\n, tempShmId);tempSmap (Stu*)shmat(tempShmId, NULL, 0); //将进程与共享内存绑定for (i 0; i 3; i){ //读数据printf(name:%s\n, (*(tempSmap i)).name);printf(age %d\n, (*(tempSmap i)).age);}//of for iif (shmdt(tempSmap) -1){ //解除绑定perror(detach error);return -1;}//of ifshmctl(tempShmId, IPC_RMID, tempBuf); //删除共享内存return 0;
}//of main6 小结
了解Linux进程间的通信方式是学习Linux编程的基础也是学习和实现复杂编程的基石。
7 编程题
1父进程向无名管道写入小写字母子进程读出后转换为大写字母写入管道父进程再将其读出 2父进程向共享内存输入字符子进程判断是否是自己要接收的信息是的话输出共享内存中的信息。