操作系统之地址映射与共享实验

实验内容

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跟踪地址翻译
操作系统之地址映射与共享实验_第1张图片
写的很乱。。。。。下回有时间再完善

编写shmget和shmat系统调用

// 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等文件。

添加sem.c信号量系统调用文件

// 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来延时处理时序上的矛盾。

编写producer.c文件

#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;
}

编写consumer.c文件

#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;
}

编译程序,运行程序

操作系统之地址映射与共享实验_第2张图片
操作系统之地址映射与共享实验_第3张图片
程序结束时,这个释放空间的时候出现了问题,我猜是共享内存释放的时候造成的,不过不影响我验证这个地址映射与共享实验,日后再完善把。

实验结果

操作系统之地址映射与共享实验_第4张图片
操作系统之地址映射与共享实验_第5张图片

总结

从上面结果看,地址的共享确实成功了。本实验中有很多待改善的地方,等有时间再完善。

你可能感兴趣的:(os操作系统)