/ get_next_line / README.md
README.md
1 # get_next_line 2 3 프로토타입: 4 5 ```c 6 char *get_next_line(int fd); 7 ``` 8 - `fd` : 파일 디스크립터 9 10 반환값: 11 12 - 만약 한 줄이 제대로 읽혔다면 개행과 함께 해당 줄이 반환. 13 14 - 제대로 읽히지 않았다면(혹은 읽을 줄이 더 이상 없다면) NULL을 반환. 15 16 ## `get_next_line` 함수란? 17 18 `get_next_line` 함수를 반복문에서 호출하면, 파일 디스크립터에 들어온 텍스트를 EOF까지 한 번에 한 줄씩 읽어들인다. 19 20 함수는 개행문자(`\n`)를 기준으로 한 줄을 판단한다. 21 22 ### 참고할 사항들 23 24 파일 디스크립터가 파일이던, 리다이렉션이던, STDIN이던, 모두 함수가 제대로 동작해야 한다. 25 26 버퍼 사이즈(`BUFFER_SIZE`)가 1이던, 9999이던, 10000000이던, 함수가 제대로 동작해야 한다. 27 28 질문점: 29 30 파일 디스크립터의 `OPEN_MAX`을 지정해주어야 할까? 31 - 아니다, OPEN_MAX를 따로 지정하는 것보단(시스템에 따라 값이 다르므로), 어차피 파일 디스크립터는 잘못된 파일을 읽는 경우 -1 을 반환하므로, 따로 설정할 필요가 없다고 생각. 32 - 하지만 배열을 이용하여 풀 경우, `ulimit` 명령어로 OPEN_MAX 값을 변경할 수 있기에, 과제의 경우 이에 대한 방어기 필요해보임. 33 - 나는 OPEN_MAX 값과 관계 없이 구조체를 추가할 수 있도록 연결리스트를 사용하였다. 34 - [https://42born2code.slack.com/archives/CMX2R5JSW/p1602999277202400](https://42born2code.slack.com/archives/CMX2R5JSW/p1602999277202400) 35 36 버퍼 사이즈도 스택 오버플로우가 나지 않게 설정을 따로 해주어야 할까? 37 - 컴파일러에 의해 자동으로 maximum stack size로 제한되는듯. 따로 설정할 필요가 없다. 38 - [https://stackoverflow.com/questions/13102642/max-size-for-char-buffer-in-c](https://stackoverflow.com/questions/13102642/max-size-for-char-buffer-in-c) 39 40 ## 정적 변수란? 41 42 정적(static) 변수는 지역 변수의 특성과 전역 변수의 특성을 합친 변수이다. 정적 변수는 아래와 같이 선언한다: 43 44 ```c 45 static 자료형 변수이름; 46 ``` 47 48 정적 변수는 함수 안에서 사용될 수 있지만, 함수를 벗어나더라도 변수가 사라지지 않고 계속 유지된다. 49 50 왜냐하면 정적 변수는 (전역 변수와 동일하게) 컴파일 시간에 데이터 영역에 메모리를 할당하고, 프로그램이 끝날 때 메모리가 해제되기 떄문이다. 51 (즉, 프로그램이 끝날 때까지 변수 안의 값이 유지된다.) 52 53 정적 변수는 초기값을 주지 않을 경우, 0 으로 초기화된다. 54 55 정적 변수는 (전역 변수와는 다르게) 외부에서 사용할 수 없다(`extern`). 또한 함수의 매개 변수로도 사용할 수 없다. 56 57 참고: 58 - [https://dojang.io/mod/page/view.php?id=690](https://dojang.io/mod/page/view.php?id=690) 59 - [https://love-every-moment.tistory.com/43](https://love-every-moment.tistory.com/43) 60 61 ### 그렇다면, `get_next_line`에서 정적 변수를 사용하는 이유는? 62 63 BONUS에서 여러 개의 파일 디스크립터를 처리하기 위해선, 함수가 끝나더라도(즉 한 줄을 읽더라도) 들어온 파일 디스크립터의 상태를 저장해야 한다. 64 65 따라서 정적 변수를 사용하여 들어온 파일 디스크립터를 모두 저장하고 읽어서, 각 파일 디스크립터에 할당된 서로 다른 파일을 한 줄 씩 차례로 출력한다. 66 67 ## 파일 디스크립터란? 68 69 리눅스와 유닉스(UNIX)에서는 (하드웨어 등 장치를 모두 포함하여) 시스템을 전부 파일로 처리하여 관리하는데, 시스템의 프로세스가 파일에 접근하기 위해선 파일 디스크립터(File Descriptor)라는 핸들이 필요하다고 한다. 70 71 파일 디스크립터는 0 이상의 정수 값(Non-negative Integer)을 갖는데, 파일 디스크립터 0, 1, 2 는 각각 표준 입력(Standard Input), 표준 출력(Standard Output) 그리고 표준 에러(Standard Error)로 미리 할당되어 있다. 72 73 파일 디스크립터는 프로그램이 시작되면 자동으로 열리고, 프로그램이 종료되면 닫힌다고 한다. 파일을 열거나 소켓을 생성하여 부여되는 파일 디스크립터는 3 부터 시작한다. 74 75 여담으로 파일 디스크립터가 단순히 숫자인 이유는, 프로세스가 유지하고 있는 파일 디스크립터 테이블의 인덱스를 지시하기 때문이다. 즉 파일 디스크립터(FD) 3번이라는 의미는, FD 테이블의 3번 항목이 가리키는 파일을 의미한다. 76 77 참고: 78 - [https://dev-ahn.tistory.com/96](https://dev-ahn.tistory.com/96) 79 - [https://wonillism.tistory.com/166](https://wonillism.tistory.com/166) 80 81 ## `read` 함수란? 82 83 `unistd.h` 헤더에 포함된 함수이다. 84 85 프로토타입: 86 87 ```sh 88 ssize_t read(int fd, void *buf, size_t nbytes); 89 ``` 90 - `fd` : 파일 디스크립터 91 - `buf` : 파일을 읽을 버퍼 92 - `nbytes` : 버퍼의 크기 93 94 반환값: 95 96 - 정상적으로 실행되었다면 읽어들인 바이트 수를 반환. 97 98 - 만약 실패하였다면 -1 을 반환. 99 100 - 더 이상 읽을 데이터가 없다면(EOF) 0을 반환. 101 102 참고: [https://badayak.com/4486](https://badayak.com/4486) 103 104 ### 참고할 사항들 105 106 `read` 함수는 버퍼의 크기만큼 읽을 수 있다면 모두 읽어들이므로, 버퍼의 크기가 파일보다 크다면 파일의 모든 내용을 읽게 된다. 반대로 파일보다 버퍼의 크기가 작다면 파일을 여러번 읽는다. 107 108 backup을 구조체에 설정하여, 읽어들인 문자열을 저장하기.