[SW사관학교 정글]64일차 TIL

김승덕·2022년 11월 22일
0

SW사관학교 정글 5기

목록 보기
104/150
post-thumbnail

argument passing(인수 전달)

목표

  • 커맨드 라인레서 명령어의 실행
  • process_exec() 안의 사용자 프로그램을 위한 인수를 설정하라

구체화

  • 커맨드 라인의 문자열을 토큰으로 분리하는 기능 개발(현재 pintos는 프로그램과 인자를 구분하지 못하는 구조)
  • 프로그램 이름과 인자를 구분하여 스택에 저장, 인자를 프로그램에 전달

수정 파일

pintos-kaist/src/userprog/process.*

예시

예를 들어 ls -l *.c 라는 명령어가 입력이 되었을때, ls , -l , *.c 로 파싱을 하고 스택에 인자를 저장하고(-l, *.c), ls 를 실행할 수 있도록 해야한다.

pintOS에서 프로그램의 실행

(주의 : 한양대 자료와 카이스트 pintos가 함수 이름이 다름 process_execute(argv) == process_create_initd (task), start_process() == process_exec (void *f_name))

추가 전

main()run_actions()run_task() (유저 프로세스 생성 후 핀토스는 프로세스 종료 대기) → process_wait(process_create_initd(task)) (자식 프로세스가 종료될 때까지 대기, 아직 구현 안됨) →
process_create_initd(task) 에서 thread_create(file_name, PRI_DEFAULT, initd, fn_copy) 실행(스레드 생성 후 run queue에 추가) → process_exec(f_name)process_cleanup()load(file_name, &_if)

process_exec(f_name) 안의 함수들

  • process_cleanup() : 초기화
  • load(file_name, &_if) : filesys에서 userprog를 mem에 적재
  • do_iret : stack에 저장한 argument를 사용해 thread 시작

추가 후

main()run_actions()run_task() (유저 프로세스 생성 후 핀토스는 프로세스 종료 대기) → process_wait(process_create_initd(task)) (자식 프로세스가 종료될 때까지 대기, 아직 구현 안됨) → 커맨드 라인에서 프로세스 이름 확인
process_create_initd(task) 에서 thread_create(file_name, PRI_DEFAULT, initd, fn_copy) 실행(스레드 생성 후 run queue에 추가) → process_exec(f_name)Argument parsing(커맨드 라인 parsing 하여 인자 확인)process_cleanup()load(file_name, &_if)void argument_stack() (인자들을 스택에 삽입)

진행 과정

process_exec(void *f_name)에서 프로그램을 메모리에 적재 후 프로그램 시작 → load()에서 프로그램을 메모리에 적재 → 메모리 적재 성공시 process_exec()에서 유저 프로그램 시작

스택을 잘 쌓아라

hex_dump 함수 사용하여 잘 출력되는것을 확인하기

포인터가 문제다.

공부하면서 찾아본 것들

변수나 함수 등에 _ (언더바)를 쓰는 이유

내부에서만 사용되는 변수나 함수에는 -언더바를 쓴다고 한다.

코드의 변수나 함수 등에 _ 언더바를 사용하는 이유는?

ELF

Executable and Linkable Format, 또는 ELF. ELF는 유닉스 계열 운영체제의 실행, 오브젝트 파일, 공유 라이브러리, 또는 코어 덤프를 할 수 있게 하는 바이너리 파일이다. 간단히, 실행 파일이다. 원래 뜻은 Extensible Linking Format 이라는 뜻을 가지고 있었다.

(출처 : https://namu.wiki/w/ELF)

strtok_r

char *
strtok_r (char *s, const char *delimiters, char **save_ptr) {
	char *token;

	ASSERT (delimiters != NULL);
	ASSERT (save_ptr != NULL);

	/* If S is nonnull, start from it.
	   If S is null, start from saved position. */
	if (s == NULL)
		s = *save_ptr;
	ASSERT (s != NULL);

	/* Skip any DELIMITERS at our current position. */
	while (strchr (delimiters, *s) != NULL) {
		/* strchr() will always return nonnull if we're searching
		   for a null byte, because every string contains a null
		   byte (at the end). */
		if (*s == '\0') {
			*save_ptr = s;
			return NULL;
		}

		s++;
	}

	/* Skip any non-DELIMITERS up to the end of the string. */
	token = s;
	while (strchr (delimiters, *s) == NULL)
		s++;
	if (*s != '\0') {
		*s = '\0';
		*save_ptr = s + 1;
	} else
		*save_ptr = s;
	return token;
}

문자열 s에서 구분자 delimeters를 기준으로 자르고 문자 처음을 리턴하고 save_ptr에 자른 다음의 문자를 포인터로 지정한다. save_ptr 전에는 '/0'으로 바꿔주어 문자를 끊어준다.

strchr

char *
strchr (const char *string, int c_) {
	char c = c_;

	ASSERT (string);

	for (;;)
		if (*string == c)
			return (char *) string;
		else if (*string == '\0')
			return NULL;
		else
			string++;
}

string에서 c가 있는지 검사해서 해당부분의 포인터 반환, 아니면 NULL반환

참고로 for(;;) 는 무한루프

[C언어/C++] strchr 함수(문자 검색)에 대해서

디버깅

  1. printf 찍어보고 아래 명령어 입력
pintos --fs-disk=10 -p tests/userprog/args-single:args-single -- -q -f run 'args-single onearg'
  1. backtrace 이용
    backtrace 뒤에 callstack 주소들 입력해보기
profile
오히려 좋아 😎

1개의 댓글

comment-user-thumbnail
2022년 11월 22일

자세한 설명 감사합니다!!!!
열공하는 모습이 보기 좋아요 ㅎㅎ

답글 달기