本次實驗在信號量的基礎上增加了共享內存,比較簡單,只需要改寫上次的pc.c代碼即可
producer.c
~~~
#define __LIBRARY__
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define Total 500
#define BUFFERSIZE 10
int main()
{
int shmid;
int put_pos = 0, i;
int *ShareAddress;
sem_t *empty, *full, *mutex;
empty = (sem_t *)sem_open("empty", O_CREAT, 0777, 10);
full = (sem_t *)sem_open("full", O_CREAT, 0777, 0);
mutex = (sem_t *)sem_open("mutex",O_CREAT, 0777, 1);
shmid = shmget( 555204, BUFFERSIZE*sizeof(int), IPC_CREAT|0666);
/*
if(!shmid)
{
printf("shmget failed!");
exit(0);
}
*/
ShareAddress = (int*)shmat(shmid, NULL, 0);
/*
if(!ShareAddress)
{
printf("shmat failed!");
exit(0);
}
*/
for( i = 0 ; i < Total; i++)
{
sem_wait(empty);
sem_wait(mutex);
ShareAddress[put_pos] = i;
put_pos = ( put_pos + 1 ) % BUFFERSIZE;
sem_post(mutex);
sem_post(full);
}
while(1);
return 0;
}
~~~
consumer.c
~~~
#define __LIBRARY__
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define Total 500
#define BUFFERSIZE 10
int main()
{
int shmid;
int get_pos = 0, i;
int *ShareAddress;
sem_t *empty, *full, *mutex;
empty = (sem_t *)sem_open("empty", O_CREAT, 0777, 10);
full = (sem_t *)sem_open("full", O_CREAT, 0777, 0);
mutex = (sem_t *)sem_open("mutex",O_CREAT, 0777, 1);
shmid = shmget( 555204, BUFFERSIZE*sizeof(int), IPC_CREAT|0666 ); /*返回共享內存的標識符*/
/* if(!shmid)
{
printf("shmget failed!");
fflush(stdout);
exit(0);
}
*/
ShareAddress = (int*)shmat(shmid, NULL, 0);
/*
if(!ShareAddress)
{
printf("shmat failed!");
fflush(stdout);
exit(0);
}
*/
for(i = 0; i < Total; i++)
{
sem_wait(full);
sem_wait(mutex);
printf("%d\n", ShareAddress[get_pos]);
fflush(stdout);
get_pos = ( get_pos + 1 ) % BUFFERSIZE;
sem_post(mutex);
sem_post(empty);
}
sem_unlink("empty");
sem_unlink("full");
sem_unlink("mutex");
return 0;
}
~~~
report
1.對于地址映射實驗部分,列出你認為最重要的那幾步(不超過4步),并給出你獲得的實驗數據。
答:第一步是:尋找保存變量i的虛擬地址ds:0x3004所對應的LDT,ldtr的值是0x0068=0000000001101000(二進制),表示LDT表存放在GDT表的1101(二進制)=13(十進制)號位置。
GDT的位置已經由gdtr明確給出,在物理地址的0x00005cb8。dl和dh的值分別為0x52d00068,0x000082fd。組合出LDT表的物理地址0x00fd52d0。
第二步是:由ds:0x0017=0000000000010111(二進制),所以RPL=11,可見是在最低的特權級(因為在應用程序中執行),TI=1,表示查找LDT表,索引值為10(二進制)= 2(十進制),
表示找LDT表中的第3個段描述符(從0開始編號)。所以第3項“0x00003fff 0x10c0f300”就是尋找的ds段描述符。
第三步是:段描述符“0x00003fff 0x10c0f300”組合成的“0x10000000”。這就是ds段在線性地址空間中的起始地址(ds段的段基址)。段基址+段內偏移,就是線性地址了。
所以ds:0x3004的線性地址就是:0x10000000 + 0x3004 = 0x10003004。
首先需要算出線性地址中的頁目錄號、頁表號和頁內偏移,它們分別對應了32位線性地址的10位+10位+12位,所以0x10003004的頁目錄號是64,頁號3,頁內偏移是4。
頁目錄表的基址為0,其中第65個頁目錄項就是我們要找的內容,0x00000100 : 0x00fa3027,頁表所在物理頁框號為0x00fa3,即頁表在物理內存的0x00fa3000位置。
進而得到0x00fa300c : 0x00fa2067
第四步是:線性地址0x10003004對應的物理頁框號為0x00fa2,和頁內偏移0x004接到一起,得到0x00fa2004,這就是變量i的物理地址。
查看0x00fa2004 : 0x12345678,證明其確實為i的物理地址。
2.test.c退出后,如果馬上再運行一次,并再進行地址跟蹤,你發現有哪些異同?為什么?
答: 相同的是虛擬地址不會改變,線性地址也不會改變,但是實際的物理地址改變了。因為虛擬地址和線性地址都是操作系統抽象出來的,再運行一次仍可以在當前位置,
而物理地址是動態分配的,可能上一次的物理地址已經被占用,所以操作系統會分配一塊新的未被使用的來保存變量的值。