使用命名管道对system-v共享内存通信实现同步机制 所谓同步机制关心的就是谁先谁后的问题本次设计代码利用读端open后只有写端打开才会读否则就会堵塞其次在client写入共享内存后才会执行write,去唤醒read,否则read会一直读到0阻塞在while循环中不会去读。架构图如下实现建立命名管道以及共享内存如下com.h// 声明信道 #pragma once #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/ipc.h #include sys/shm.h #include sys/stat.h #include errno.h #include fcntl.h #define Path . #define proj_id 0x0666 #define SHM_SIZE 4096 #define ERR_TYPE(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while (0) // 建立共享内存 int create_shm(size_t size); // 销毁共享内存 int destroy_shm(int shmid); // 获取共享内存 int get_shm(size_t size); // 链接共享内存 void *attach_shm(int shmid); // 断开共享内存 void detach_shm(void *shmaddr); //创建命名管道实现同步 int create_pipe(char *pipe_name, mode_t mode);com.c#include com.h // 建立共享内存 static int commshm(size_t size, int flags); int create_shm(size_t size) { umask(0); return commshm(size, IPC_CREAT | IPC_EXCL | 0666); } // 该实现函数本地私有化 static int commshm(size_t size, int flags) { key_t key ftok(Path, proj_id); if (key -1) { ERR_TYPE(ftok); return -1; } int shmid 0; if ((shmid shmget(key, size, flags)) -1) { ERR_TYPE(shmget); return -2; } return shmid; } // 销毁共享内存 int destroy_shm(int shmid) { if (shmctl(shmid, IPC_RMID, NULL) -1){ ERR_TYPE(shmctl); return -3; } return 0; } // 获取共享内存 int get_shm(size_t size) { return commshm(size, 0); } // 链接共享内存 void *attach_shm(int shmid) { if(shmat(shmid, NULL, 0) (void *)-1){ ERR_TYPE(shmat); return (void*)-4; } return shmat(shmid, NULL, 0); } // 断开共享内存 void detach_shm(void *shmaddr) { if(shmdt(shmaddr) -1){ ERR_TYPE(shmdt); } } //创建命名管道实现同步 int create_pipe(char *pipe_name, mode_t mode){ if(mkfifo(pipe_name, mode) -1){ ERR_TYPE(mkfifo); return -1; } return 0; }sever.c//服务端建立共享内存信道 #include com.h int main(){ //创建共享内存返回内存数组值 int shmid create_shm(SHM_SIZE); //链接共享内存 char* addr attach_shm(shmid); //创建命名管道实现互斥 int retcreate_pipe(my_pipe, 0666); if(ret -1){ ERR_TYPE(create_pipe); return -1; } sleep(2); //打印用户写进来的数据 int i40; printf(写端打开等待读端:\n); int rfdopen(my_pipe, O_RDONLY); printf(服务端接收数据中:\n); if(rfd -1){ ERR_TYPE(ropen); return -1; } char* buffer[40]{0}; //read唤醒 //如果写端没写完就阻塞 printf(等待写端阻塞中.............\n); while(i--read(rfd, buffer, 2) 0){ //提取共享内存到输出流 printf(用户发来: %s\n, addr); fflush(stdout); sleep(1); } printf(服务端接收数据完成\n); //分离共享内存 detach_shm(addr); printf(分离共享内存\n); sleep(1); //删除共享内存 destroy_shm(shmid); printf(删除共享内存\n); sleep(1); //删除命名管道 close(rfd); unlink(my_pipe); printf(删除命名管道\n); sleep(1); }client.c//客户端获取共享内存信道 #include com.h int main(){ //获取共享内存 int shmid get_shm(SHM_SIZE); //链接共享内存 char* addr attach_shm(shmid); char* baseaddr; sleep(2); //打开读端 printf(打开读端:\n); int rfdopen(my_pipe, O_WRONLY); if(rfd -1){ ERR_TYPE(wopen); return -1; } //用户写数据 int i65; printf(用户写入数据中:\n); sleep(5); char* buffer[40]{0}; while(i90){ snprintf(addr,SHM_SIZE, %c, i); snprintf(addr1,SHM_SIZE, %c, i); write(rfd, buffer, 2); printf(写端写入唤醒读进程\n); i; addr2; sleep(1); } printf(用户写入数据完成\n); sleep(2); //分离共享内存 detach_shm(base); sleep(1); printf(用户分离共享内存\n); //关闭管道文件描述符 close(rfd); sleep(1); printf(用户关闭管道文件描述符\n); return 0; }MakefileCC : gcc CFLAGS : -Wall -Wextra -stdc11 -g all: client server client: client.c com.c com.h $(CC) $(CFLAGS) -o client client.c com.c server: server.c com.c com.h $(CC) $(CFLAGS) -o server server.c com.c clean: rm -f client server .PHONY: all clean运行结果如下