Исходные коды с внесенными модификациями и комментариями

Userprog/syscall.c

#include "userprog/syscall.h"

#include <stdio.h>

#include <syscall-nr.h>

#include "threads/interrupt.h"

#include "threads/thread.h"

#include <list.h>

#include "threads/init.h"

#include "lib/kernel/stdio.h"

#include "userprog/process.h"

#include "filesys/filesys.h"

#include "devices/input.h"

//deskriptor

struct fd_des{

int fd; //unique num

struct file *file; //opened file

struct list_elem elem;

struct list_elem t_elem; //processes lists

};

void halt(void);/*

int wait(int pid);

int exit(int status);

int create (const char *file, unsigned int initial_size);

int exec(const char *cmd_line);

int open(const char *file);

int close (int fd);

int write(int fd, const void *buffer, unsigned size);

int read(int fd, void *buffer, unsigned size);

static struct fd_des *find_fd_elem_by_fd(int fd);

static struct file *find_file_by_fd(int fd);*/

//struct of all user's processes

struct list file_list;

//lock

struct list file_lock;

static void syscall_handler (struct intr_frame *);

void

syscall_init (void)

{

intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall");

list_init(&file_list);

list_init(&file_lock);

}

static void

syscall_handler (struct intr_frame *f /*UNUSED*/)

{

int sys_num=*(int*)(f->esp);

switch(sys_num){

case SYS_HALT:

halt;

break;

/*case SYS_EXIT:

exit(*(int*)(f->esp+4));

break;

case SYS_EXEC:

f->eax=exec(*(char*)(f->esp+4));

break;

case SYS_WAIT:

f->eax=wait(*(int*)(f->esp+4));

break;

case SYS_CREATE:

f->eax=create(*(char*)(f->esp+4),*(int*)(f->esp+8));

break;

case SYS_READ:

f->eax=read(*(int*)(f->esp+4), *(char*)(f->esp+8), *(int*)(f->esp+12));

break;

case SYS_OPEN:

f->eax=open(*(char*)(f->esp+4));

break;

case SYS_WRITE:

f->eax=write(*(int*)(f->esp+4), *(char*)(f->esp+8), *(int*)(f->esp+12));

break;

case SYS_CLOSE:

f->eax=close(*(int*)(f->esp+4));

break;*/

default:

break;

}

//printf ("system call!\n");

//thread_exit ();

}

//Ended OS Pintos.

void halt(void)

{

shutdown_power_off();

}

/*

static struct fd_des *find_fd_elem_by_fd(int fd)

{

struct fd_des *des;

struct list_elem *l;

for(l=list_begin(&file_list); l!=list_end(&file_list);l=list_next(l));

{

des=list_entry(l,struct fd_des, elem);

if(des->fd==fd)

return des;

}

return NULL;

}

static struct file *find_file_by_fd(int fd)

{

struct fd_des *t=find_fd_elem_by_fd(fd);

if(!t)

return NULL;

return t->file;

}

//Waits while daughter process with id PID ends and returns statusof its ending.

int wait(int pid)

{

return process_wait(pid);

}

//Ended user's programm returned status. status 0 - ok

int exit(int status)

{

struct thread *t=thread_current();

struct list_elem *l;

printf("%s, exit %d.\n", thread_current()->name, status);

while (!list_empty (&t->files))

{

l=list_begin(&t->files);

close(list_entry(l,struct fd_des, t_elem)->fd);

}

thread_exit();

return -1;

}

//creates a new file «file» with size initial_size. returns TRUE if ok, otherwise FALSE.

int create (const char *file, unsigned int initial_size)

{

if(!file)

return exit(1);

return filesys_create(file, initial_size);

}

//starts file, which name is in cmd_line and returns new user's process id. Returns -1 if false

int exec(const char *cmd_line)

{

if(!cmd_line)

return -1;

return process_execute(cmd_line);

}

//open file named «file». Return fd or -1 if fail. fd 0 - STDIN_FILENO, fd 1 -STDOUT_FILENO.

int open(const char *file)

{

int temp=1;

struct file *f=filesys_open(file);

if(!file || !f)

return -1;

struct fd_des *des=(struct fd_des*)malloc(sizeof (struct fd_des));

if(!des)

{

file_close(f);

return -1;

}

des->file=f;

des->fd=++temp;

list_push_back (&file_list, &des->elem);

list_push_back(&thread_current()->files, &des->t_elem);

return (des->fd);

}

int close (int fd)

{

struct fd_des *des;

des=find_fd_elem_by_fd(fd);

if(!des)

return 0;

file_close(des->file);

list_remove(&des->elem);

list_remove(&des->t_elem);

//free(des);

return 0;

}

//writes SIZE byte to the fd file. returns num of recorded bytes or -1 if fail. if fd=1 then

// system must do console output

int write(int fd, const void *buffer, unsigned size)

{

struct file *file;

int length=-1;

lock_acquire(&file_lock);

if(fd == STDOUT_FILENO)

{

putbuf(buffer, size);

lock_release(&file_lock);

return size;

}

else if (fd == STDIN_FILENO)

goto finish;

else

{

file=find_file_by_fd(fd);

if(!file)

goto finish;

length=file_write(file,buffer,size);

}

finish:

lock_release(&file_lock);

return (length);

}

int read(int fd, void *buffer, unsigned size)

{

struct file *file;

int status=-1,i;

lock_acquire(&file_lock);

if(fd == STDIN_FILENO)

{

for(i = 1; i != size; i++)

*(uint8_t*)(buffer+i)=input_getc();

status=size;

goto finish;

}

else if (fd=STDOUT_FILENO)

goto finish;

else

{

file=find_file_by_fd(fd);

if(!file)

goto finish;

status=file_read(file,buffer,size);

}

finish:

lock_release(&file_lock);

return status;

}*/

Результат

После внесения модификаций я пробовал запустить некоторые тесты из Приложения III, где перечислен список тестов для системных вызовов. Они завершались приведенной ниже ошибкой Error 1 без объяснения.

После этого я сократил оператор switch до одного варианта: функции halt(), т.к. в ней мы вызываем готовую функцию завершения работы ОС Pintos и ничего не подаем на вход функции. Запустил тест halt и вышла снова эта ошибка.

Исходные коды с внесенными модификациями и комментариями - student2.ru

Ответы на контрольные вопросы

1. В чем заключается идея системных вызовов?

Системные вызовы обеспечивают взаимосвязь между ядром и программами пользователя.

  1. В ОС Pintos используется только одно прерывание 0x30 и только один обработчик прерываний syscall_handler для всех системных вызовов. Как различить в syscall_handler системные вызовы?

Простым оператором switch и считанными из стека данными.

  1. Стандартом в построении операционных систем является следующее требование: системные вызовы read() и write() могут быть использованы только после вызова open(), а завершение их работы сопровождается вызовом close(). В чем причина появления этого требования? Почему нельзя иметь системные вызовы read() и write() без предварительного обращения к open() и close()?

Я бы назвал это чисто логическим требованием. Сначала мы открываем файл, потом читаем/записываем, потом закрываем.

  1. Что произойдет, если процесс-потомок завершится раньше, чем процесс-предок осуществит системный вызов wait()?

Перед вызовом wait() осуществляется проверка статуса процесса-потомка. Если у потомка статус THREAD_DYING, тогда я осуществил вывод THREAD_ERROR.

  1. В чем отличие в обработке внутренних и внешних прерываний в ОС Pintos? В ОС UNIX?

Внешние можно отключить с помощью intr_disable();

Наши рекомендации