一 跟踪地址翻译过程
#include <stdio.h>
int i = 0x12345678;
int main(void)
{
printf("The logical/virtual address of i is 0x%08x", &i);
fflush(stdout);
while (i);
return 0;
}
//将上述程序在linux-0.11编译运行,不出所料,死循环
//bochs反汇编查看
//很容易看出这里i的虚拟地址为ds:0x3004,接下来让我们一步步查段表查页表来找出i的物理地址.
//sreg打印cpu状态的所有信息
//由ds段选择子的二进制表示10111可知对应的段描述符在LDT中,且位于第三项的位置. 由ldtr的二进制表示1101000可知该LDT位于GDT的第14号位置,下面打印该LDT描述符信息
//由LDT描述符组合出该LDT的物理地址0x00fc82d0,下面打印该LDT的第三项即ds段描述符信息
//计算得出段基地址0x10000000,加上原来的0x3004偏移地址即得到了线性地址0x10003004,线性地址二进制表示为1 0000 0000 0000 0011 0000 0000 0100 可以得到页目录号为64,页号为3,页内偏移为4,下面查看页目录表的基地址
//IA-32下,页目录表的位置由CR3寄存器指引
//下面查看页目录第65项内容
//得到页表地址为0xfa6000,下面查看页号地址
//有了物理页框地址,加上页内偏移0x4,得到的就是变量i的物理地址0xfa3004
//意料之中,果然是i的值
//将i的物理地址存放的值赋值为0,可以看到Bochs中的程序终止.
二 Ubuntu共享内存
/*
ubuntu_producer.c
生产者进程
*/
#include<stdio.h>
#include<fcntl.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#define TOTALNUM 512
#define BUFSIZE 10
int main(int argc,char* argv[]){
sem_t *empty,*full,*mutex;
int i;
key_t key;
int shmid;
int* p;
int buf_in=0;
//创建3个信号量
if((empty=sem_open("empty", O_CREAT|O_RDWR, 0666,BUFSIZE))==SEM_FAILED){
perror("sem_open() error");
return -1;
}
if((full=sem_open("full", O_CREAT|O_RDWR,0666, 0))==SEM_FAILED){
perror("sem_open() error");
return -1;
}
if((mutex=sem_open("mutex", O_CREAT|O_RDWR,0666,1))==SEM_FAILED){
perror("sem_open() error");
return -1;
}
//获得shmget所需要的key
if((key=ftok("/tmp", 6))==-1){
perror("ftok() error");
return -1;
}
//获得分配的共享内存id
if((shmid=shmget(key, 12, IPC_CREAT|0666))==-1){
perror("shmget() error");
return -1;
}
//连接共享内存,将内存物理地址映射到进程的空闲虚拟地址空间
if((p=shmat(shmid, NULL, 0))==(void*)-1){
perror("shmat() error");
return -1;
}
//生产者
for(i=0;i<TOTALNUM;i++){
sem_wait(empty);
sem_wait(mutex);
p[buf_in]=i;
buf_in=(buf_in+1)%BUFSIZE;
sem_post(mutex);
sem_post(full);
printf("Producing %d\n", i);
fflush(stdout);
}
//关闭信号量
sem_unlink("empty");
sem_unlink("full");
sem_unlink("mutex");
//删除共享内存
if((shmctl(shmid, IPC_RMID, NULL))==-1){
perror("shmctl() error");
return -1;
}
return 0;
}
/*
ubuntu_consumer.c
消费者进程
*/
#include<stdio.h>
#include<fcntl.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#define TOTALNUM 512
#define BUFSIZE 10
int main(int argc,char* argv[]){
sem_t *empty,*full,*mutex;
int i;
key_t key;
int shmid;
int* p;
int buf_out=0;
int data;
//连接信号量
if((empty=sem_open("empty", O_RDWR, 0666,BUFSIZE))==SEM_FAILED){
perror("sem_open() error");
return -1;
}
if((full=sem_open("full", O_RDWR, 0666,0))==SEM_FAILED){
perror("sem_open() error");
return -1;
}
if((mutex=sem_open("mutex", O_RDWR, 0666,1))==SEM_FAILED){
perror("sem_open() error");
return -1;
}
//获得key
if((key=ftok("/tmp", 6))==-1){
perror("ftok() error");
return -1;
}
//获得共享内存id
if((shmid=shmget(key, 0, 0))==-1){
perror("shmget() error");
return -1;
}
//将共享内存的物理地址映射到进程的空闲虚拟地址空间
if((p=shmat(shmid, 0,SHM_RDONLY))==(void*)-1){
perror("shmat() error");
return -1;
}
//消费者
for(i=0;i<TOTALNUM;i++){
sem_wait(full);
sem_wait(mutex);
data=p[buf_out];
buf_out=(buf_out+1)%BUFSIZE;
sem_post(mutex);
sem_post(empty);
printf("Consuming %d\n", data);
fflush(stdout);
}
return 0;
}
//先运行生产者
//然后运行消费者