익명 사용자
로그인하지 않음
계정 만들기
로그인
youngwiki
검색
System-Level I/O 문서 원본 보기
youngwiki
이름공간
문서
토론
더 보기
더 보기
문서 행위
읽기
원본 보기
역사
←
System-Level I/O
문서 편집 권한이 없습니다. 다음 이유를 확인해주세요:
요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다:
사용자
.
문서의 원본을 보거나 복사할 수 있습니다.
상위 문서: [[컴퓨터 시스템]] ==개요== 입출력(I/O)은 주기억장치(main memory)와 디스크 드라이브, 터미널, 네트워크와 같은 외부 장치(external devices) 사이에서 데이터를 복사하는 과정이다. 입력 연산(input operation)은 I/O 장치로부터 데이터를 주기억장치로 복사하고, 출력 연산(output operation)은 데이터를 주기억장치에서 장치로 복사한다.<br> 해당 문서에서는 UNIX I/O와 표준 I/O의 일반적인 개념과, C 프로그램에서 이를 안정적으로 사용하는 방법을 설명한다. ==UNIX I/O== 리눅스 파일은 아래와 같은 m 바이트의 시퀸스로 구성된다. B<sub>1</sub>, B<sub>2</sub>, ..., B<sub>k</sub>, ..., B<sub>m-1</sub> 모든 I/O 장치들(예: 네트워크, 디스크, 터미널, 커널! 등)은 아래와 같이 파일로 모델링되며, 모든 I/O는 해당 파일들을 읽고 쓰는 방식으로 수행된다. /dev/sda2 (/usrdiskpartition) /dev/tty2 (terminal) /boot/vmlinuz-3.13.0-55-generic (kernel image) /proc (kernel data structures) I/O 장치들을 모두 파일로 매핑하는 방식 덕분에, 리눅스 커널은 '''UNIX I/O'''로 불리는 단순하고 저수준(low-level)의 인터페이스를 제공할 수 있다. 이를 통해 모든 I/O 작업들을 일관되고 통일된 방식으로 수행할 수 있다. ==Files== 각 리눅스 시스템 내에서의 역할을 나타내는 type을 가진다: * '''일반 파일(regular file)은 임의의 데이터로 구성'''된다. 애플리케이션 들은 종종 일반 파일 들을 ASCII 혹은 유니코드 문자만을 포함하는 텍스트 파일(text file)과, 그 외의 모든 것을 포함하는 바이너리 파일(binary file) 을 구분하지만, 커널은 이를 구분하지 않는다. 따라서 '''UNIX I/O도 텍스트 파일과 바이너리 파일을 구분하지 않는다.''' 리눅스 텍스트 파일은 단순히 '''텍스트 라인들의 시퀸스(sequence of text lines)'''로 구성되며, 각 줄(text line)은 '''문자들의 시퀸스(sequence of characters)로 이루어지고 줄바꿈 문자('\n')<ref>줄 바꿈 문자는 0x0a에 해당하며, 이는 ASCII 값과 동일하다.</ref>로 종료'''된다. * '''디렉토리(directory)'''는 '''링크(link)들의 배열로 구성'''된 파일이며, 각 '''링크는 파일 이름을 파일(혹은 디렉토리)에 매핑'''한다. 각 디렉토리는 적어도 두 개의 항목을 가지고 있다. 먼저 '''<code>.</code>는 디렉토리 자신'''을 가리키는 링크이고, '''<code>..</code>는 디렉토리 계층 구조에서 상위 디렉토리'''를 가리키는 링크이다. 디렉토리는 <code>mkdir</code> 명령어로 만들 수 있고, <code>ls</code> 명령어로 안의 내용을 볼 수 있으며, <code>rmdir</code> 명령어를 통해서 삭제할 수 있다. * [[Application Layer#Process communicating#Socket|소켓(socket)]]은 네트워크를 통해 다른 프로세스와 통신하기 위해 사용되는 파일이다. 그외에도 named pipe, symbolic link, character and block deviced와 같은 여러 type들이 추가로 존재하나, 이에 대해서는 다루지 않느다. ===Directory hierarchy=== [[파일:Portion of the Linux directory hierarchy.png|대체글=Figure 1. Portion of the Linux directory hierarchy|가운데|섬네일|400x400픽셀|Figure 1. Portion of the Linux directory hierarchy]] 리눅스 커널은 모든 파일을 루트(root) 디렉터리 <code>/</code>로 고정된 단일 디렉터리 계층 구조 안에 조직한다. 시스템 내의 각 파일은 루트 디렉터리의 직계 또는 간접 후손(direct or indirect descendant)이다. Figure 1은 리눅스 시스템 내의 디렉토리 계층의 일부를 보여준다.<br> 각 프로세스는 컨텍스트의 일부로 현재의 작업 디렉터리(current working directory)를 가지며, 이는 디렉토리 계층 내에서 현재 위치를 나타낸다. 이때, <code>cd</code> 명령어를 통해 셸(shell)의 현재 작업 디렉터리를 변경할 수 있다. 디렉더리 계층에서의 위치는 경로명(pathname) 으로 지정된다. 경로명은 <code>/</code>로 구분된 일련의 파일 이름들로 구성된 문자열이다.<ref>이때 경로명은 <code>/</code>으로 시작할 수도, 안할 수도 있다.</ref> 경로명은 두 가지 형태가 있다: * '''절대 경로명(absolute pathname)''': '''<code>/</code>로 시작하며, 루트 디렉토리로부터의 경로를 나타낸다.''' ** hello.c의 절대 경로명: <code>/home/droh/hello.c</code> * '''상대 경로명(relative pathname)''': '''파일 이름으로 시작하며, 현재 작업 디렉터리로부터의 경로를 나타낸다.''' ** <code>/home/droh</code>가 현재 작업 디렉터리일 때 hello.c의 상대 경로명: <code>./hello.c</code> ** <code>/home/bryant</code>가 현재 작업 디렉터리일 때 hello.c의 상대 경로명: <code>../home/droh/hello.c</code> ==Opening and Closing Files== ===Opening files=== 애플리케이션은 <code>close()</code> 함수를 통해 커널에게 특정 파일을 열도록 요철하며, 해당 I/O 장치에 접근한다. <syntaxhighlight lang="cpp"> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(char *filename, int flags, mode_t mode); //Returns: new file descriptor if OK, −1 on error </syntaxhighlight> 커널은 해당 파일 이름을 파일 디스크립터(file descriptor)<ref>0 이상의 정수이다</ref>로 변환하고 그 디스크립터 번호를 반환한다. 반환되는 디스크립터는 항상 프로세스에서 현재 열려 있지 않은 가장 작은 디스크립터 번호이다. 이 디스크립터는 이후 파일에 대한 모든 연산에서 사용된다.<ref>커널은 열려있는 파일에 대한 모든 정보를 추적하고 관리하나, 애플리케이션은 디스크립터만을 추적한다.</ref> 위 <code>close()</code> 함수에서 flag 인자는 프로세스가 파일에 어떻게 접근하려는지를 나타내며, 이는 아래와 같다: * O_RDONLY: 읽기 전용 * O_WRONLY: 쓰기 전용 * O_RDWR: 읽기 및 쓰기 또한, flags 인자는 추가적인 옵션을 제공하는 하나 이상의 비트 마스크(bit mask)와 OR 연산으로 결합될 수 있다. * O_CREAT: 파일이 존재하지 않으면 빈 파일을 새로 만든다. * O_TRUNC: 파일이 이미 존재하면 해당 파일을 빈 파일로 만든다. * O_APPEND: 쓰기 작업(<code>write()</code>)을 할 때마다, 커널이 자동으로 파일의 맨 끝으로 이동해서 쓰게 한다.<ref>기존 내용을 덮어 쓰지 않고 이어 쓰고자 할 때 이용한다.</ref> 예를 들어, 이어 쓰고자 할 때, 파일을 쓰기 전용으로 여는 방법은 다음과 같다. <syntaxhighlight lang="cpp"> fd = Open("foo.txt", O_WRONLY|O_APPEND, 0); </syntaxhighlight> 또한 모든 리눅스 프로세스는 생성되거나 시작하는 즉시 기본으로 열려있는 세개의 파일(디스크립터)를 가지고 있는데, 이는 다음 표와 같다: {| class="wikitable" |+ !이름 !디스크립터 !상수 !역할 |- |standard input |0 |STDIN_FILENO |키보드 등에서 입력 받기 |- |standard output |1 |STDOUT_FILENO |화면(터미널)으로 출력하기 |- |standard error |2 |STDERR_FILENO |에러 메시지 출력하기 |} ==Colsing files== 애플리케이션이 파일에 대한 접근을 마치면, <code>close()</code> 함수를 호출하여 해당 파일을 닫아달라고 커널에 요청한다: <syntaxhighlight lang="cpp"> #include <unistd.h> int close(int fd); //Returns: 0 if OK, −1 on error </syntaxhighlight> 커널은 위 함수의 호출 결과로 파일을 열 때 생성한 데이터 구조들을 해제하고, 디스크립터를 사용 가능한 디스크립터 풀로 되돌린다. 이때 이미 닫혀있는 디스크립터를 닫는 것은 오류이다. 또한 프로세스가 어떤 이유로든 종료되면, 커널은 열려있는 모든 파일들을 닫고 그 메모리 자원들을 해제한다. <syntaxhighlight lang="cpp"> </syntaxhighlight> <syntaxhighlight lang="cpp"> </syntaxhighlight> <syntaxhighlight lang="cpp"> </syntaxhighlight> ==각주== [[분류:컴퓨터 시스템]]
System-Level I/O
문서로 돌아갑니다.
둘러보기
둘러보기
대문
최근 바뀜
임의의 문서로
미디어위키 도움말
위키 도구
위키 도구
특수 문서 목록
문서 도구
문서 도구
사용자 문서 도구
더 보기
여기를 가리키는 문서
가리키는 글의 최근 바뀜
문서 정보
문서 기록