今天早上完成了第五次实验的第二部分,这部分要求在ubuntu上用共享内存模拟生产者消费者问题,期间要用到之前的信号量。
producer.c 中,我用shmget开出一页内存共享,其返回值是一个比较大的整数,这个整数在整个系统中都是通用的,其他程序都可一通过这个id来共享我开出的这一页 内存,用于进程间的交流。用shmat函数来获得这个共享页的使用权限,申请使用这个页,然后这个函数会返回给你一个*buf的八位地址值,这个地址值就 是所有程序共用的共享内存地址,正常的程序,如果不采用共享内存,那么他们即使对同一个地址进行操作都是互补相干的,因为他们索访问到的地址都是相对自己 段地址的偏移量,每个程序都是有自己的内存区域的,所以虽然你可以写一个一样的地址大小,但是那只是偏移量,不是同一个地方。而注册过共享页后,共享页 shmat回馈给你的这个八位地址就是相同位置的了,这时候你们再做什么操作就是对同一块物理内存了。这个八位地址可以随便用,非常灵活,不许要 malloc什么的,直接就可以访存,所以如果是多进程的话那就要注意临界区的上锁保护了。
producer.c:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/ipc.h> 5 #include <sys/shm.h> 6 #include <semaphore.h> 7 #include <pthread.h> 8 #include <fcntl.h> 9 #include <unistd.h> 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 13 #define BUFSZ 64 14 15 main() 16 { 17 int i, shmid, test; 18 char *shmbuf; 19 sem_t *full, *empty; 20 21 sem_unlink("full"); 22 sem_unlink("empty"); 23 full = sem_open("full", O_CREAT, 0777, 0); 24 empty = sem_open("empty", O_CREAT, 0777, 10); 25 shmid = shmget(IPC_PRIVATE, BUFSZ, 0666); 26 printf("shmid: %d\n", shmid); 27 shmbuf = shmat(shmid, 0, 0); 28 29 for (i = 0; i < BUFSZ; ++i) { 30 sem_wait(empty); 31 shmbuf[i] = i; 32 printf("write: shmbuf[%d] = %d\n", i, shmbuf[i]); 33 sem_post(full); 34 } 35 36 printf("Written"); 37 scanf("%d", &i); 38 shmdt(shmbuf); 39 return 0; 40 } 41 42 consumer.c: 43 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <sys/types.h> 47 #include <sys/ipc.h> 48 #include <sys/shm.h> 49 #include <semaphore.h> 50 #include <pthread.h> 51 #include <fcntl.h> 52 #include <unistd.h> 53 #include <sys/types.h> 54 #include <sys/stat.h> 55 56 #define BUFSZ 64 57 58 main() 59 { 60 int i, shmid, test; 61 char *shmbuf; 62 sem_t *full, *empty; 63 64 full = sem_open("full", O_CREAT); 65 empty = sem_open("empty", O_CREAT); 66 scanf("%d", &shmid); 67 shmbuf = shmat(shmid, 0, 0); 68 69 for (i = 0; i < BUFSZ; ++i) { 70 sem_wait(full); 71 printf("read: shmbuf[%d]: %d\n", i, shmbuf[i]); 72 sem_post(empty); 73 } 74 75 shmdt(shmbuf); 76 return 0; 77 }
最后效果是在gdb上看到的,不然的话两者的速度太快,看不出来效果。我先运行producer,他就会在第十次write停止,然后我用gdb一拍一拍单步运行,可以看到明显效果:

浙公网安备 33010602011771号