feat[OS/win4]: сделал эту еб**ую лабу
This commit is contained in:
222
OSs/lab-virt-win/main.c
Normal file
222
OSs/lab-virt-win/main.c
Normal file
@ -0,0 +1,222 @@
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
THREAD_SIM,
|
||||
THREAD_MONITOR,
|
||||
THREAD_NUM
|
||||
};
|
||||
|
||||
HANDLE threads[THREAD_NUM];
|
||||
int threads_params[THREAD_NUM];
|
||||
SYSTEM_INFO sys_info;
|
||||
|
||||
DWORD WINAPI thread_sim(LPVOID param);
|
||||
DWORD WINAPI thread_monitor(LPVOID param);
|
||||
|
||||
#define SIMOP_EXIT 0x00
|
||||
#define SIMOP_RESERVE 0x01
|
||||
#define SIMOP_PASS_BLOCK 0x02
|
||||
#define SIMOP_NON_SAVE 0x03
|
||||
#define SIMOP_FREE_REG 0x04
|
||||
#define SIMOP_RETURN_BLOCK 0x05
|
||||
#define SIMOP_LOCK_BLOCK 0x06
|
||||
#define SIMOP_UNLOCK_BLOCK 0x07
|
||||
#define SIMOP_MESS_REGION 0x08
|
||||
|
||||
#define SLEEP_MILLIS 2000
|
||||
|
||||
// Некоторые поля увелчены для выравнивания
|
||||
struct sim_cmd{
|
||||
uint64_t millis_offset;
|
||||
uint64_t op;
|
||||
uint64_t region;
|
||||
uint64_t reg_sz;
|
||||
uint64_t access;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
GetSystemInfo(&sys_info);
|
||||
threads[THREAD_SIM] = CreateThread(NULL, 0, thread_sim,
|
||||
&threads_params[THREAD_SIM], 0, NULL);
|
||||
if (!threads[THREAD_SIM]) {
|
||||
printf("Couldn't create simulator\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
threads[THREAD_MONITOR] = CreateThread(NULL, 0, thread_monitor,
|
||||
&threads_params[THREAD_MONITOR], 0, NULL);
|
||||
if (!threads[THREAD_MONITOR]) {
|
||||
printf("Couldn't create monitor\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto close_sim_thread;
|
||||
}
|
||||
|
||||
printf("waiting...\n");
|
||||
DWORD status = WaitForMultipleObjects(THREAD_NUM, threads, TRUE, INFINITE);
|
||||
printf("done waiting (%lu).\n", GetLastError());
|
||||
|
||||
close_monitor_thread:
|
||||
CloseHandle(&threads[THREAD_MONITOR]);
|
||||
close_sim_thread:
|
||||
CloseHandle(&threads[THREAD_SIM]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read_sim_cmd(FILE *src, struct sim_cmd *dest)
|
||||
{
|
||||
const size_t cmd_sz = sizeof(struct sim_cmd);
|
||||
size_t bytes_read = fread(dest, sizeof(char), cmd_sz, src);
|
||||
if (bytes_read != cmd_sz) return -ENODATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_sim_cmd(FILE *src, struct sim_cmd *dest)
|
||||
{
|
||||
const size_t cmd_sz = sizeof(struct sim_cmd);
|
||||
size_t bytes_written = fwrite(dest, sizeof(char), cmd_sz, src);
|
||||
if (bytes_written != cmd_sz) return -ENODATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define QUIT_NUMBER 'q'
|
||||
|
||||
static uint64_t last_clock = 0;
|
||||
static int do_cmd(struct sim_cmd *cmd)
|
||||
{
|
||||
if (cmd->millis_offset > last_clock) Sleep(cmd->millis_offset - last_clock);
|
||||
switch (cmd->op) {
|
||||
case SIMOP_RESERVE:
|
||||
if (!VirtualAlloc((LPVOID)cmd->region, cmd->reg_sz,
|
||||
MEM_RESERVE | MEM_COMMIT, cmd->access)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
case SIMOP_FREE_REG:
|
||||
if (VirtualFree((LPVOID)cmd->region, cmd->reg_sz, MEM_DECOMMIT) == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case SIMOP_LOCK_BLOCK:
|
||||
if (VirtualLock((LPVOID)cmd->region, cmd->reg_sz) == 0) {
|
||||
return -ENOLCK;
|
||||
}
|
||||
break;
|
||||
case SIMOP_UNLOCK_BLOCK:
|
||||
if(VirtualUnlock((LPVOID)cmd->region, cmd->reg_sz) == 0) {
|
||||
return -ENOLCK;
|
||||
}
|
||||
break;
|
||||
case SIMOP_PASS_BLOCK:
|
||||
if (!VirtualAlloc((LPVOID)cmd->region, cmd->reg_sz, MEM_COMMIT, cmd->access)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
case SIMOP_NON_SAVE:
|
||||
if (!VirtualAlloc((LPVOID)cmd->region, cmd->reg_sz,
|
||||
MEM_RESERVE | MEM_RESET, cmd->access)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
case SIMOP_RETURN_BLOCK:
|
||||
if (!VirtualFree((LPVOID)cmd->region, 0, MEM_RELEASE)) {
|
||||
printf("error was %lu\n", GetLastError());
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
case SIMOP_MESS_REGION:
|
||||
printf("messing with pages...\n");
|
||||
if (cmd->access == PAGE_READWRITE || cmd->access == PAGE_EXECUTE_READWRITE) {
|
||||
printf("memsetting\n");
|
||||
memset((LPVOID)cmd->region, 0x77, cmd->reg_sz);
|
||||
} else if (cmd->access == PAGE_READONLY) {
|
||||
#define BUFF_SIZE 256
|
||||
printf("reading to buffer...\n");
|
||||
char buff[BUFF_SIZE] = {0};
|
||||
for (size_t i = 0; i < cmd->reg_sz; i += BUFF_SIZE) {
|
||||
memcpy(buff, &((char*)(cmd->region))[i], BUFF_SIZE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SIMOP_EXIT:
|
||||
return QUIT_NUMBER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI thread_sim(LPVOID param)
|
||||
{
|
||||
DWORD status = 0;
|
||||
FILE *program = fopen("vm.bin", "r");
|
||||
if (!program) {
|
||||
printf("can't open file vm.bin\n");
|
||||
status = EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
static struct sim_cmd cmd;
|
||||
while(read_sim_cmd(program, &cmd) == 0) {
|
||||
int ret = do_cmd(&cmd);
|
||||
printf("command (%02llx) done with code (%d)\n", cmd.op, ret);
|
||||
status = abs(ret);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
} else if (ret == QUIT_NUMBER) {
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close_program:
|
||||
fclose(program);
|
||||
exit:
|
||||
printf("return from vm\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
int write_report(FILE *f)
|
||||
{
|
||||
MEMORYSTATUS ms;
|
||||
GlobalMemoryStatus(&ms);
|
||||
size_t bytes_written = fprintf(
|
||||
f,
|
||||
"Memory status (Total/Avail):\n"
|
||||
"Physical: %zu/%zu\n"
|
||||
"Virtual: %zu/%zu\n"
|
||||
"Page file: %zu/%zu\n"
|
||||
"Page size (bytes): %lu\n"
|
||||
"Granularity: %lu\n\n",
|
||||
ms.dwTotalPhys, ms.dwAvailPhys,
|
||||
ms.dwTotalVirtual, ms.dwAvailVirtual,
|
||||
ms.dwTotalPageFile, ms.dwAvailPageFile,
|
||||
sys_info.dwPageSize,
|
||||
sys_info.dwAllocationGranularity
|
||||
);
|
||||
if (bytes_written < 1) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI thread_monitor(LPVOID param)
|
||||
{
|
||||
DWORD status = 0;
|
||||
FILE *report = fopen("report.txt", "w");
|
||||
if (!report) {
|
||||
printf("fault\n");
|
||||
status = EFAULT;
|
||||
goto close_report;
|
||||
}
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
Sleep(SLEEP_MILLIS);
|
||||
printf("report written with status: %d\n", write_report(report));
|
||||
}
|
||||
close_report:
|
||||
fclose(report);
|
||||
return status;
|
||||
}
|
||||
Reference in New Issue
Block a user