2012.8.11 - Linux内核开发 - 地址映射与共享

Posted on 2013-02-20 14:31  SnakeHunt2012  阅读(302)  评论(0)    收藏  举报

今天早上完成了第五次实验的第二部分,这部分要求在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一拍一拍单步运行,可以看到明显效果: