Linux多进程间通信——共享内存实现聊天室程序
Linux多进程间通信——共享内存实现聊天室程序
上一讲我们用共享内存实现了进程间的简单通信,一个进程写,一个进程读,我们这次增加一点难度,创建两块共享内存,来实现一个简单的聊天室程序。
先自己动手做一下,再来看源码。
下面给出源码,一共有四个进程,两两实现通信,互相收发消息
shmmutexRW_Server.c代码如下:
#include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> int main(){ sem_t *sem_1;//定义信号量 sem_t *sem_2; int shmid[2];//共享内存ID struct Student{ char name[20]; int age; int number; }; struct Student *shmaddr[2]; //创建信号量来实现读写锁,读写不能同时进行 sem_1 = sem_open("sem_1", O_CREAT, 0644, 1); sem_2 = sem_open("sem_2", O_CREAT, 0644, 1); //创建子进程 pid_t pid; pid = fork(); if(pid < 0){ perror("cannot fork! "); return -1; } else if(pid == 0){ //子进程,用共享内存shmaddr[0]来接收shmMutexRW_Server.c子进程的消息 key_t shmkey; shmkey = ftok("/etc", 0);//创建共享内存的标识 shmid[0] = shmget(shmkey, 100, 0666|IPC_CREAT); if(shmid[0] == -1){ printf("shmget failed "); exit(0); } shmaddr[0] = (struct Student*)shmat(shmid[0], 0, 0); if(shmaddr[0] == (struct Student*)-1){ printf("shmat failed "); exit(0); } //开始读此进程中的数据并显示 shmaddr[0]->age = 0; while(1){ sem_wait(sem_1); if(shmaddr[0]->age > 0){ printf("子进程Server读到共享内存中的数据:姓名:%s ", shmaddr[0]->name); shmaddr[0]->age--; } sem_post(sem_1); } sem_close(sem_1); if(shmdt(shmaddr[0]) == -1) printf("shmdt failed "); if(shmctl(shmid[0], IPC_RMID, NULL) == -1) printf("shmctl failed "); } else{ //父进程,向共享内存shmaddr[1]中写入数据,供shmMutexRW_Server.c的父进程读数据 //创建共享内存shmaddr[1] key_t shmkey1 = ftok("/bin", 0); shmid[1] = shmget(shmkey1, 100, 0666|IPC_CREAT); if(shmid[1] == -1){ printf("shmget failed "); exit(0); } shmaddr[1] = (struct Student*)shmat(shmid[1], 0, 0); if(shmaddr[1] == (struct Student*)-1){ printf("shmat failed "); exit(0); } shmaddr[1]->age = 0;//这里很关键,还是信号量的赋初值很关键? while(1){ sem_wait(sem_2); memset(shmaddr[1]->name, 0, 20); printf("写进程:请输入姓名(不超过20字符)到共享内存: "); if(fgets(shmaddr[1]->name, 20, stdin) == NULL){ perror("fgets failed "); sem_post(sem_2); break; } shmaddr[1]->age++; sem_post(sem_2); sleep(1); } sem_close(sem_2); if(shmdt(shmaddr[1]) == -1){ printf("shmdt failed "); } if(shmctl(shmid[1], IPC_RMID, NULL)){ printf("shmctl failed "); } } sem_unlink("shmaddr[0]_RW"); sem_unlink("shmaddr[1]_RW"); return 0; }
这里shmmutexRW_Client.c的源码我就不再给出了,读者们可以根据上一讲的内容来自己实现一下。
程序运行的效果如下: