반응형

File

유닉스에서 파일의 특징에는 다음과 같은 것들이 있다.

A container of data : 데이터를 포함하는 컨테이너

File is a contiguous sequence of bytes : 연속된 바이트의 서열

No format imposed by the operating system : OS가 정한 파일의 형태가 특정되지 않음

Each byte is individually addressable in a disk file : 모든 바이트는 디스크 파일에서 주소 지정 가능

File is also a uniform interface to external devices : 외부 장치의 인터페이스들 조차 파일로 간주

 

Filesystem

파일 시스템

컴퓨터 파일과 데이터를 정리하고 저장하는 방법

파일에 접근하기 쉽다.

파일 시스템은 데이터 저장장치(하드디스크, CD-ROM)를 사용할 수 있다.

 

File System Interface란 System call을 말한다. 기본적으로는 (open, create, close, read, write, lseek, unlink, remove, fcntl)가 있다.

유저 프로그램(User app)이 system call을 부르기 위해서 trap(s/w interrupt)을 발생시키면, File System Management, Hardware Control을 통해서 Hardware 장치로 전달된다. 

 

이때 Disk와 같은 block 장치인지, 키보드와 같은 character 장치인지에 따라 적절한 디바이스 드라이버를 이용하여 Hardware Control로 진행된다. character의 경우 입출력 한 단위가 1byte이지만, block의 경우 1block이 4KB이기에 buffer cache가 필요하다. 

 

위 함수들은 표준화된 C가 아닌 POSIX.1과 XPG3 즉 UNIX 표준에 포함되어있다. 

또한 라이브러리에는 버퍼가 없다. (커널 버퍼를 말하는 것이 아님)

File Descriptor

커널에서 파일을 열 때, 지정하는 번호를 말한다. 이때 지정되는 번호는 음수가 아닌 정수들이다.

파일을 새로 만들거나 기존의 파일을 열 때, 즉 open이나 create명령어를 사용할 때 커널이 file descriptor를 반환해준다. 

file descriptor를 read나 write로 넘겨주어 해당 파일에 대한 read와 write를 진행할 수 있다.

 

유닉스에서 process를 만들면 기본적으로 다음과 같은 세 개의  file descriptor가 할당된다. 

File descriptor Symbolic constant describe
0 STDIN_FILENO Standard input
1 STDOUT_FILENO Standard output
2 STDERR_FILENO Standard error

0번은 표준입력이다. (컴퓨터에서는 사용자의 표준입력이 키보드인 셈이다) 1번과 2번은 표준 출력 즉 스크린으로 출력함을 의미하는데 정상적인 출력이냐 에러출력이냐를 구분한다.

 

위 0,1,2의 file descriptor가 생성시 할당되므로, open 명령어를 통해 파일을 처음 열면 '3'번이 나온다. 사용되지 않는 음이 아닌 정수 중 가장 작은수를 반환하는 것이다. 

 

예제코드

/* a rudimentary example program */

/* these header files are discussed below */
#include <fcntl.h>
#include <unistd.h>

main()
{
    int fd; // file descriptor
    ssize_t nread;
    char buf[1024];

    /* open file “data” for reading */
    fd = open(“data”, O_RDONLY); 
    // 위 "data"라는 파일에 해당하는 경로는 상대경로로 현재경로인 working directory
    // O_RDONLY 는 open_mode로 read only를 의미

    /* read in the data */
    nread = read(fd, buf, 1024);
    // fd 파일의 1024byte를 읽어 buf에 담는다.
    
    /* close the file */
    close(fd);
}

처음으로 open을 통해 파일을 열면 fd에는 0,1,2,는 생성이 할당이 이미 되었으므로 3이 반환된다. 이 번호가 "data"라는 이름의 파일을 지정하는 번호이다. 

 이 번호(fd)를 가지고 read를 한다. read명령어를 실행할 때 파일의 크기가 1024만큼 되지 않고 예를들어 100byte라고 한다면, 100byte만큼만을 읽어오고 읽어온 byte수를 nread로 반환한다.

 close를 통해 파일을 닫는다.

 

헤더에 대해서 알아보자

 혹시나 헤더의 <>에 대해서 설명하자면, /usr/include/헤더파일명 을 의미한다. 즉 "/usr/include"가 default 디렉토리인 셈이다. 

fcntl.h 헤더는 open 시스템 콜이 선언되어있고, unistd.h 헤더에는 ssize_t 자료형이 포함되어있다. ssize_t는 int인데 typedef로 이름만 바꾸어 놓은 것이다. 자료형을 따로 설정한 이유는 read의 반환값으로 받는 값의 자료형이 시스템마다 short, long 등 다양하기 때문에 표준화한 것이다. (ssize_t가 unistd.h에 포함되어있고, sys/types.h헤더는 unistd.h를 포함한다)

예를들어 다른 환경에서는 sys 헤더에 ssize_t 자료형이 int가 아니라 short로 처리되어있고, 그걸 ssize_t 자료형을 통해 표준화하여 쓰는 것이다.

환경별로 다른 자료형을 충돌없이 숨기기 위해서 sys/types.h의 typedef로 선언된 자료형을 사용하는 것이다. 

 

 

반응형

'Computer Science > UNIX' 카테고리의 다른 글

UNIX - File permissions 파일 권한  (0) 2021.09.15
UNIX system call - open  (0) 2021.09.14
UNIX의 파일체계  (0) 2021.09.13
UNIX의 구조와 기본적인 개념들  (0) 2021.09.05
Virtual Box 설치하기  (0) 2021.09.04
UNIX의 역사  (0) 2021.09.02

+ Recent posts