크래프톤 정글 일지

[PintOS] User Programs - 함수들

나한나한나한나 2024. 5. 20. 22:28
void halt(void);​

 

Pintos를 종료하기 위해 'devices/shutdown.h'에 선언된 shutdown_power_off()를 호출합니다. 이는 잠재적인 교착 상황에 대한 일부 정보를 잃기 때문에 드물게 사용해야 합니다.

void exit (int status);

현재 사용자 프로그램을 종료하고 상태를 커널에 반환합니다. 프로세스의 부모가 기다리는 경우 (아래 참조), 이것이 반환될 상태입니다. 전통적으로 0의 상태는 성공을 나타내고 0이 아닌 값은 오류를 나타냅니다.

pid_t exec(const char *cmd_line);

cmd_line에 주어진 이름의 실행 파일을 실행하고 주어진 인수를 전달한 후 새로운 프로세스의 프로그램 ID(pid)를 반환합니다. 프로그램이 어떤 이유로든 로드되거나 실행되지 않으면 그 결과가 일반적으로 유효한 PID가 아닌 -1이어야 합니다. 따라서 부모 프로세스는 자식 프로세스가 실행 파일을 성공적으로 로드했는지 여부를 알 때까지 exec에서 반환하지 않습니다. 이를 위해 적절한 동기화를 사용해야 합니다.

int wait(pid_t pid);

pid로 지정된 자식 프로세스를 기다리고 자식의 종료 상태를 검색합니다. 만약 pid가 아직 살아 있다면 종료될 때까지 기다립니다. 그런 다음 pid가 exit()를 호출할 때 전달한 상태를 반환합니다. 만약 pid가 exit()를 호출하지 않았지만 커널에 의해 종료되었다면 (예: 예외로 인한 종료) wait(pid)는 -1을 반환해야 합니다. 부모 프로세스가 wait를 호출할 때 이미 종료된 자식 프로세스에 대해 기다릴 수 있지만, 커널은 여전히 부모가 자식의 종료 상태를 검색하거나 커널에 의해 자식이 종료되었음을 알 수 있게 해야 합니다. wait는 다음 조건 중 하나라도 참일 경우 즉시 실패하고 -1을 반환해야 합니다:

  • pid가 호출하는 프로세스의 직접적인 자식을 참조하지 않음. pid가 호출하는 프로세스의 직접적인 자식이 되려면 호출 프로세스가 exec를 성공적으로 호출한 후 pid를 반환받았어야 합니다. 프로세스는 모든 자식을 스폰할 수 있고 어떤 순서로든 기다릴 수 있으며 일부 또는 모든 자식을 기다리지 않고도 종료할 수 있습니다. 디자인은 모든 대기가 발생할 수 있는 방식을 고려해야 합니다. 프로세스의 모든 리소스, 즉 구조체 스레드를 부모가 기다리든 기다리지 않든 그리고 자식이 부모보다 이전에 또는 이후에 종료되든 모두 해제되어야 합니다. 초기 프로세스가 종료될 때까지 Pintos가 종료되지 않도록 보장해야 합니다. 제공된 Pintos 코드는 'userprog/process.c'의 process_wait() (threads/init.c의 main()에서)를 호출하여 이를 수행하려고 합니다. process_wait()를 함수 상단의 주석에 따라 구현하고 그 후 wait 시스템 호출을 process_wait()을 기반으로 구현하는 것이 좋습니다. 이 시스템 호출을 구현하는 것은 다른 모든 것보다 훨씬 더 많은 작업이 필요합니다.
bool create(const char *file, unsigned initial_size);

file이라는 이름의 새 파일을 초기 크기가 initial_size인 크기로 생성합니다. 성공하면 true를 반환하고, 그렇지 않으면 false를 반환합니다. 새 파일을 생성하는 것은 파일을 열지 않습니다. 새 파일을 열기 위해서는 따로 open 시스템 호출이 필요합니다.

bool remove(const char *file);

file이라는 이름의 파일을 삭제합니다. 성공하면 true를 반환하고, 그렇지 않으면 false를 반환합니다. 파일이 열려 있든 닫혀 있든 파일을 삭제할 수 있으며, 열린 파일을 삭제해도 닫히지 않습니다. 자세한 내용은 [열려 있는 파일 삭제], 35페이지를 참조하십시오.

int open(const char *file);

file이라는 이름의 파일을 엽니다. "파일 디스크립터"라고 하는 음수가 아닌 정수 핸들 (fd)을 반환하거나 파일을 열 수 없는 경우 -1을 반환합니다. 파일 디스크립터 0과 1은 콘솔에 예약되어 있습니다. fd 0 (STDIN_FILENO)은 표준 입력이고, fd 1 (STDOUT_FILENO)은 표준 출력입니다. open 시스템 호출은 이러한 파일 디스크립터 중 하나를 반환하지 않으며, 이들은 명시적으로 아래에서 설명된 시스템 호출의 인수로만 유효합니다. 각 프로세스는 독립적인 파일 디스크립터 세트를 갖습니다. 파일 디스크립터는 자식 프로세스에게 상속되지 않습니다. 동일한 파일을 하나의 프로세스나 다른 프로세스에서 여러 번 열면 각각의 open이 새로운 파일 디스크립터를 반환합니다. 동일한 파일에 대한 다른 파일 디스크립터는 단독으로 close 호출로 닫히며 파일 위치를 공유하지 않습니다.

int filesize(int fd);

fd로 열린 파일의 크기(바이트 단위)를 반환합니다.

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

fd로 열린 파일에서 size 바이트를 buffer로 읽습니다. 실제로 읽은 바이트 수를 반환합니다 (파일의 끝에서는 0), 파일을 읽을 수 없는 경우 -1을 반환합니다 (파일 끝 이외의 조건으로 인해). Fd 0은 input_getc()를 사용하여 키보드에서 읽습니다.

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

buffer에서 열린 파일 fd로 size 바이트를 씁니다. 실제로 쓴 바이트 수를 반환합니다. 일부 바이트를 쓸 수 없는 경우 size보다 적게 반환될 수 있습니다. 파일의 끝을 넘어 쓰기는 일반적으로 파일을 확장하지만 기본 파일 시스템에는 파일 확장이 구현되어 있지 않습니다. 예상 동작은 파일의 끝까지 가능한 한 많은 바이트를 쓰고 실제로 쓴 바이트 수를 반환하거나 전혀 쓸 수 없는 경우 0을 반환하는 것입니다. Fd 1은 콘솔에 씁니다. 콘솔에 쓰기 위한 코드는 putbuf()를 한 번의 호출로 buffer의 모든 내용을 쓰도록 해야 합니다. 적어도 size가 몇 백 바이트보다 크지 않는 한 (큰 버퍼를 분할하는 것이 합리적입니다). 그렇지 않으면 서로 다른 프로세스에 의해 출력된 텍스트 줄이 콘솔에서 뒤섞일 수 있으므로 인간 독자와 채점 스크립트 모두 혼란스러워질 수 있습니다.

void seek(int fd, unsigned position);

열린 파일 fd의 다음 바이트를 파일의 시작부터 position으로 변경합니다. (즉, 위치 0은 파일의 시작입니다.) 현재 파일의 끝을 초과하는 seek는 오류가 아닙니다. 이후의 읽기는 0바이트를 얻어 파일의 끝을 나타냅니다. 이후의 쓰기는 파일을 확장하여 쓰지 않은 간격을 0으로 채웁니다. (그러나 Pintos 파일은 프로젝트 4가 완료될 때까지 고정된 길이를 갖기 때문에 파일의 끝을 넘어 쓰기는 오류를 반환합니다.) 이러한 의미론은 파일 시스템에 구현되어 있으며 시스템 호출 구현에서 특별한 노력이 필요하지 않습니다.

unsigned tell(int fd);

열린 파일 fd에서 다음에 읽거나 쓰여질 바이트의 위치를 파일의 시작부터 바이트로 표시하여 반환합니다.

void close(int fd);

파일 디스크립터 fd를 닫습니다. 프로세스를 종료하거나 종료하는 것은 모든 열린 파일 디스크립터를 암시적으로 닫습니다. 마치 이 함수를 각각 호출하는 것처럼입니다.