linux下进程间共享内存通信的问题

linux下进程间共享内存通信的问题

我在学习linux进程间的共享内存通信时,遇到了很多问题,就想把这些问题记下来,当做一个学习笔记。

先简单介绍一下共享内存通信:

共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。

通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。

共享内存往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。否则,就可能出现无法意料的错误。

因为共享内存在进程结束后不会自动删除,所以你要在确保没有进程使用共享内存的时候,删除它,否则就可能造成内存泄露。

创建共享内存通信的基本步骤:

(1)首先由需要通信的任意一方进程创建一个共享内存区,并返回可供通信双方进程访问的该共享内存区的一个标识,但一定要确保两个进程得到的标识是一样的,否则,就读写的不是同一个共享内存。(2)共享内存区非创建进程将共享内存区通过其标识绑定到本进程(3)通信双方进程可以读写共享内存区(4)通信结束后,双方进程脱离共享内存区(5)任意一方通信进程删除共享内存区

我在学习老师给提供的两个进程间共享内存通信的例子时,,时不时出现一些非常奇怪的错误,比如说,在写进程运行过后,运行读进程,出现没有共享内存的错误等等。

最后,我才发现了问题出在了那里,下面来一一说明:

给出老师给的两个程序(经过了我的修改):

写入程序:

/*************************************************************************> File Name: shmmutexwrite.c> Author: gwq> Mail: 457781132@qq.com > Created Time: 2014年10月13日 星期一 16时53分28秒 ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <string.h>#define SEM_KEY 1234#define SHM_KEY 1235#define SHM_SIZE (1024 * 1024)// 1M#define BUFFER_SIZE 1024// 1Kstruct people {char name[BUFFER_SIZE];int age;};union semun {int val;struct semid_ds *buf;ushort *array;};//信号量的P操作void p(int semid){//成员一定要初始化struct sembuf sem_p;sem_p.sem_op = -1;sem_p.sem_num = 0;sem_p.sem_flg = 0;if (semop(semid, &sem_p, 1) == -1) {perror("semop");printf("p operation is fail!\n");}}//信号量的V操作void v(int semid){//成员一定要初始化struct sembuf sem_v;sem_v.sem_op = 1;sem_v.sem_num = 0;sem_v.sem_flg = 0;if (semop(semid, &sem_v, 1) == 1) {perror("semop");printf("v operation is fail!\n");}}int main(int argc, char *argv[]){int semid;int shmid;int age = 10;int i = 1;char buff[BUFFER_SIZE];//key_t semkey = ftok("shmmutexwrite.c", 0);//key_t shmkey = ftok("shmmutexread.c", 0);key_t semkey = SEM_KEY;key_t shmkey = SHM_KEY;//创建共享内存和信号量的IPCif ((semid = semget(semkey, 1, 0666 | IPC_CREAT)) == -1) {perror("semget");printf("creat sem is fail!\n");exit(EXIT_FAILURE);}if ((shmid = shmget(shmkey, SHM_SIZE, 0666 | IPC_CREAT)) == -1) {perror("shmget");printf("creat shm is fail!\n");exit(EXIT_FAILURE);}//设置信号量的初始值为1,就是资源个数union semun sem_u;sem_u.val = 1;semctl(semid, 0, SETVAL, sem_u);//将共享内存映射到当前进程的地址中,之后直接对进程中的地址addr操作//就是对共享内存操作struct people *addr = (struct people *)shmat(shmid, NULL, 0);if (addr == (struct people *)-1) {perror("shmat");printf("shm shmat is fail!\n");exit(EXIT_FAILURE);}//向共享内存写入数据addr->age = 0;//第1个元素作为可供消费的产品数量不存放产品do {p(semid);//信号值减1memset(buff, 0, BUFFER_SIZE);memset((addr + i)->name, 0, BUFFER_SIZE);printf("写进程:输入一些姓名(不超过%d个字符)到共享""内存(输入\&;quit\&;退出):\n", BUFFER_SIZE);if (fgets(buff, BUFFER_SIZE, stdin) == NULL) {perror("fgets");printf("fgets input error!\n");v(semid);exit(EXIT_FAILURE);}strncpy((addr + i)->name, buff, strlen(buff) – 1);(addr + i)->age = ++age;addr->age++;i++;v(semid);} while (strncmp(buff, "quit", 4) != 0);if (shmdt(addr) == -1) {perror("shmdt");printf("shmdt is fail\n");exit(EXIT_FAILURE);}return 0;}读入程序:

/*************************************************************************> File Name: shmmutexread.c> Author: gwq> Mail: 457781132@qq.com > Created Time: 2014年10月13日 星期一 16时53分28秒 ************************************************************************/#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <string.h>#include <stdlib.h>#define SEM_KEY 1234#define SHM_KEY 1235#define SHM_SIZE (1024 * 1024)// 1M#define BUFFER_SIZE 1024// 1Kstruct people {char name[BUFFER_SIZE];int age;};//信号量的P操作void p(int semid){//成员一定要初始化struct sembuf sem_p;sem_p.sem_op = -1;sem_p.sem_num = 0;sem_p.sem_flg = 0;if (semop(semid, &sem_p, 1) == -1) {perror("semop");printf("p operation is fail\n");}}//信号量的V操作void v(int semid){//成员一定要初始化struct sembuf sem_v;sem_v.sem_num = 0;sem_v.sem_op = 1;sem_v.sem_flg = 0;if (semop(semid, &sem_v, 1) == 1) {perror("semop");printf("v operation is fail\n");}}int main(int argc, char *argv[]){int semid;int shmid;int i = 1;//key_t semkey = ftok("shmmutexwrite.c", 0);//key_t shmkey = ftok("shmmutexread.c", 0);key_t semkey = SEM_KEY;key_t shmkey = SHM_KEY;//创建共享内存和信号量的IPCif ((semid = semget(semkey, 1, 0666)) == -1) {perror("semget");printf("creat sem is fail!\n");exit(EXIT_FAILURE);}if ((shmid = shmget(shmkey, 0, 0666)) == -1) {perror("shmget");printf("creat shm is fail!\n");exit(EXIT_FAILURE);}//将共享内存映射到当前进程的地址中,之后直接对进程中的地址addr操作//就是对共享内存操作struct people *addr;addr = (struct people *)shmat(shmid, NULL, 0);if (addr == (struct people *)-1) {perror("shmat");printf("shm shmat is fail!\n");exit(EXIT_FAILURE);}//从共享内存读出数据do {p(semid);if (addr->age > 0) {addr->age–;if (strncmp((addr + i)->name, "quit", 4) == 0) {break;}printf("\n读进程:绑定到共享内存%p:%d 姓名 %s,年龄 %d\n",addr, i, (addr + i)->name, (addr + i)->age);++i;}v(semid);} while (1);//将共享内存与当前进程断开if (shmdt(addr) == -1) {perror("shmdt");printf("shmdt is fail\n");}//IPC必须显示删除。否则会一直留存在系统中if (semctl(semid, 0, IPC_RMID, 0) == -1) {perror("semctl");printf("semctl delete error\n");}if (shmctl(shmid, IPC_RMID, NULL) == -1) {perror("shmctl");printf("shmctl delete error\n");}return 0;}

写进程的作用是先创建一个共享内存,然后向里边写入内容,读进程的作用是打开一个已经存在的共享内存,从里边读取写进程写入的内容,并打印到终端上。要求是写进程先运行。

下边一一说明我遇到的问题:

一,ftok函数

就是这个函数的使用不当造成了前面提到的那个问题,写进程运行后,运行读进程报错,提示找不到共享内存。

微笑的去寻找一个不可能出现的你。

linux下进程间共享内存通信的问题

相关文章:

你感兴趣的文章:

标签云: