1、用Bochs调试工具跟踪Linux 0.11的地址翻译(地址映射)过程,了解IA-32和Linux 0.11的内存理机制。
2、在Ubuntu上编写多进程的生产者—消费者程序,用共享内存做缓冲。
3、在信号量实验的基础上,为Linux 0.11增加共享内存功能,并将生产者—消费者程序移植到Linux 0.11。
1、编写view-memory.c文件:
#include
int i = 0x12345678;
int main(void)
{
printf("The logic or virtual address of i is 0x%08x\n", &i);
while(i);
return 0;
}
2、使用bochs跟踪地址翻译
写的很乱。。。。。下回有时间再完善
// linux-0.11/mm/shm.c
#include
#include
#include
#define COUNT (10)
#define SIZE_MAX (4096)
unsigned long share_physical_address[COUNT] = {0};
/* create or open a page of the share memroy */
int sys_shmget(int key, size_t size, int shmflg)
{
// forbid it that more than 4K size
if (key < 0 || key >= COUNT || size > SIZE_MAX)
{
errno = EINVAL;
return -1;
}
// allocate a page of the free page from the physical memroy
if (0 == share_physical_address[key])
{
share_physical_address[key] = get_free_page();
if (0 == share_physical_address[key])
{
errno = EINVAL;
return -1;
}
}
printk("sys_shmget: address = %d\n", share_physical_address[key]);
return share_physical_address[key];
}
/* get logic address of the memory address */
int sys_shmat(int shmid, const void *shmaddr, int shmflg)
{
unsigned long data_base = 0;
unsigned long data_limit = 0;
if (shmid == -1)
{
errno = EINVAL;
return 0;
}
// establish a mapping between the physical page and the current virtual breakpoint
put_page(shmid, (current->start_code + current->brk));
printk("sys_shmat: current->brk = %d\n", current->brk);
return current->brk;
}
然后再更改一些编译这系统调用的依赖,通过修改Makefile、system_call.s等文件。
// linux-0.11/kernel/sem.c
#include
#include
#include
#include
#include
#include
#define MAX_NAME_LEN (32)
#define MAX_SEM_NUM (64)
struct sem_s {
char name[MAX_NAME_LEN];
int max_value;
int value;
struct task_struct *b_wait;
int enable;
};
typedef struct sem_s sem_t;
struct sem_list_info {
sem_t *sem_list[MAX_SEM_NUM];
int index;
};
struct sem_list_info sem_info = {0};
static void get_fs_buff(const char *name, char*buff, int size)
{
int i;
memset(buff, 0, size);
for (i = 0; i < size; i++)
{
buff[i] = get_fs_byte(name++);
if (buff[i] == '\0')
{
break;
}
}
}
static int find_sem(const char *name, char *buf)
{
int i = 0;
get_fs_buff(name, buf, 1024);
for (i = 0; i < MAX_SEM_NUM; i++)
{
if (!sem_info.sem_list[i])
{
continue;
}
printk("find_sem: sem_info.sem_list[i]->name = %s\n", sem_info.sem_list[i]->name);
if (0 == strcmp(sem_info.sem_list[i]->name, buf))
{
printk("find_sem: buf = %s\n", buf);
return i;
}
}
return -1;
}
int sys_sem_open(const char *name, unsigned int value)
{
sem_t *sem = 0;
int i = 0;
char buf[1024] = {0};
int index = find_sem(name, buf);
printk("sys_sem_open: %s\n", buf);
cli();
if (-1 == index) // new sem, need create it
{
for (i = 0; i < MAX_SEM_NUM; i++)
{
if (!sem_info.sem_list[i])
{
sem_info.sem_list[i] = malloc(sizeof(sem_t));
sem_info.sem_list[i]->max_value = value;
sem_info.sem_list[i]->value = value;
sem_info.sem_list[i]->enable = 1;
strcpy(sem_info.sem_list[i]->name, buf);
printk("sys_sem_open: %s, i = %d\n", buf, i);
sem = sem_info.sem_list[i];
index = i;
break;
}
}
}
else
{
sem_info.sem_list[index]->enable = 1;
sem = sem_info.sem_list[index];
}
sti();
printk("sys_sem_open: %s, index = %d\n", sem_info.sem_list[i]->name, index);
return sem;
}
int sys_sem_wait(sem_t *sem)
{
if (!sem || !sem->enable) {return -1;}
int i = 0;
cli();
if (--sem->value < 0) // if the value is less than 0, save the info and enter the schedule
{
sleep_on(&(sem->b_wait));
}
sti();
return i;
}
int sys_sem_post(sem_t *sem)
{
if (!sem || !sem->enable) {return -1;}
int i = 0;
cli();
sem->value++;
wake_up(&(sem->b_wait));
sti();
return i;
}
int sys_sem_unlink(const char *name)
{
int i = 0;
char buf[1024] = {0};
int index = find_sem(name, buf);
cli();
if (index >= 0 && sem_info.sem_list[index])
{
free(sem_info.sem_list[index]);
printk("sys_sem_unlink: %s\n", buf);
}
sti();
return i;
}
怎么说呢,这个sem.c可以验证本实验,但是由于时序上没有做严格处理,所以需要待完善的。这里我用一些printk来延时处理时序上的矛盾。
#include
#include
#include
#include
#include
int sem_open(const char* name,unsigned int value)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (72),"b" ((long)(name)),"c" ((long)(value)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int sem_wait(sem_t* sem)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (73),"b" ((long)(sem)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int sem_post(sem_t* sem)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (74),"b" ((long)(sem)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int sem_unlink(const char* name)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (75),"b" ((long)(name)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int shmget(int key, size_t size,int shmflg)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (76),"b" ((long)(key)),"c" ((long)(size)),"d" ((long)(shmflg)));
if (__res>=0)
return (int) __res;
errno=-__res;
return -1;
}
int shmat(int shmid, const void * shmaddr, int shmflg)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (77),"b" ((long)(shmid)),"c" ((long)(shmaddr)),"d" ((long)(shmflg)));
if (__res>=0)
return (int) __res;
errno=-__res;
return -1;
}
void write_buff(FILE *fl, int data, int pos)
{
fseek(fl, 4 * pos, SEEK_SET);
fwrite(&data, sizeof(int), 1, fl);
fflush(fl);
}
void read_buff(FILE *fl, int *data, int pos)
{
fseek(fl, 4 * pos, SEEK_SET);
fread(data, sizeof(int), 1, fl);
}
char *buff = 0;
int *value_index = 0;
int main(int argc, char **argv)
{
#define BUFF_LEN (10)
#define MAX_SIZE (120)
int shmid = 0;
int share_memory_address = 0;
sem_t *sem_empty = NULL;
sem_t *sem_full = NULL;
sem_t *sem_mutex = NULL;
int i = 0;
FILE *result = NULL;
char *end_flag = 0;
result = fopen("/var/restt", "wb+");
if (result == NULL)
{
printf("can not open result buff by wb+ \n");
return 0;
}
shmid = shmget(0, 0, 0);
if (shmid == -1)
{
printf("can not allocate the share memory \n");
return 0;
}
share_memory_address = shmat(shmid, 0, 0);
if (share_memory_address == 0)
{
printf("can not allocate the virtual memory \n");
return 0;
}
buff = (char*)share_memory_address;
end_flag = (char*)(share_memory_address + 12);
value_index = (int*)(share_memory_address + 16);
*(int*)(share_memory_address + 22) = 1234;
sem_empty = (sem_t *)sem_open("EMPTY", BUFF_LEN);
sem_full = (sem_t *)sem_open("FULL", 0);
sem_mutex = (sem_t *)sem_open("MUTEX", 1);
for (i = 0; i <= MAX_SIZE; i++)
{
sem_wait(sem_empty);
sem_wait(sem_mutex);
buff[*value_index] = i;
fseek(result, 2, SEEK_END);
fprintf(result, "write: %d, write_index:%d\n", buff[*value_index], *value_index);
fflush(result);
*value_index = (*value_index + 1) % BUFF_LEN;
sem_post(sem_mutex);
sem_post(sem_full);
}
while(*end_flag != 123); // wait for the consumer being finshed
fclose(result);
sem_unlink("EMPTY");
sem_unlink("FULL");
sem_unlink("MUTEX");
printf("producer end\n");
fflush(stdout);
return 0;
}
#include
#include
#include
#include
#include
int sem_open(const char* name,unsigned int value)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (72),"b" ((long)(name)),"c" ((long)(value)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int sem_wait(sem_t* sem)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (73),"b" ((long)(sem)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int sem_post(sem_t* sem)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (74),"b" ((long)(sem)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int sem_unlink(const char* name)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (75),"b" ((long)(name)));
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
int shmget(int key, size_t size,int shmflg)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (76),"b" ((long)(key)),"c" ((long)(size)),"d" ((long)(shmflg)));
if (__res>=0)
return (int) __res;
errno=-__res;
return -1;
}
int shmat(int shmid, const void * shmaddr, int shmflg)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (77),"b" ((long)(shmid)),"c" ((long)(shmaddr)),"d" ((long)(shmflg)));
if (__res>=0)
return (int) __res;
errno=-__res;
return -1;
}
void write_buff(FILE *fl, int data, int pos)
{
fseek(fl, 4 * pos, SEEK_SET);
fwrite(&data, sizeof(int), 1, fl);
fflush(fl);
}
void read_buff(FILE *fl, int *data, int pos)
{
fseek(fl, 4 * pos, SEEK_SET);
fread(data, sizeof(int), 1, fl);
}
char *buff = 0;
int main(int argc, char **argv)
{
#define BUFF_LEN (10)
#define MAX_SIZE (120)
int shmid = 0;
int share_memory_address = 0;
sem_t *sem_empty = NULL;
sem_t *sem_full = NULL;
sem_t *sem_mutex = NULL;
int i = 0;
int index = 0;
int count = 0;
FILE *result = NULL;
int *end_flag = 0;
int data = 0;
result = fopen("/var/restt", "a");
if (result == NULL)
{
printf("can not open result buff by wb+ \n");
return 0;
}
shmid = shmget(0, 0, 0);
if (shmid == -1)
{
printf("can not allocate the share memory \n");
return 0;
}
share_memory_address = shmat(shmid, 0, 0);
if (share_memory_address == 0)
{
printf("can not allocate the virtual memory \n");
return 0;
}
buff = (char*)share_memory_address;
end_flag = (char*)(share_memory_address + 12);
data = *(int*)(share_memory_address + 22);
printf("data: %d \n", data);
sem_empty = (sem_t *)sem_open("EMPTY", BUFF_LEN);
sem_full = (sem_t *)sem_open("FULL", 0);
sem_mutex = (sem_t *)sem_open("MUTEX", 1);
for (;;)
{
sem_wait(sem_full);
sem_wait(sem_mutex);
fseek(result, 2, SEEK_END);
fprintf(result, "pid:%d: read data = %d, read index = %d\n", getpid(), buff[index], index);
fflush(result);
index = (index + 1) % BUFF_LEN;
count++;
if (count >= MAX_SIZE + 1)
{
*end_flag = 123;
printf("consumer:end_flag = %d\n", *(char*)(share_memory_address + 12));
break;
}
sem_post(sem_mutex);
sem_post(sem_empty);
}
printf("consumer end\n");
return 0;
}
程序结束时,这个释放空间的时候出现了问题,我猜是共享内存释放的时候造成的,不过不影响我验证这个地址映射与共享实验,日后再完善把。
从上面结果看,地址的共享确实成功了。本实验中有很多待改善的地方,等有时间再完善。