地址映射与共享

一 跟踪地址翻译过程
#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;
}

//先运行生产者
这里写图片描述

//然后运行消费者
这里写图片描述

这里写图片描述

三 Linux0.11上实现共享内存
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值