유닉스는 파일에 대해서 파일의 기능을 심플하게 함
파일
파일은 데이터를 포함하는 컨테이너라고 정의함
파일은 연속된 바이트의 시퀀스라고 정의함
파일에는 어떤 포멧도 정해져있지 않음
(메인프레임의 경우 파일의 종류가 많았음 isam, random, vsam file, 등
파일의 종류에 따라 엑세스하는 API가 모두 다르고, 이를 OS가 다 정의해서 굉장히 무거웠음)
모든 바이트는 디스크 파일에서 바이트 하나하나 주소를 지정함, 다이렉트 랜덤 파일이 된다는 말임
파일에 관한 인터페이스를 다 uniform 하게 통일시킴
심지어는 외부의 디바이스 파일, 디스크 파일, 키보드, 유에스비, 마그네틱 테이프 등 모두 파일로 간주
모든 디바이스의 인터페이스를 다 통일함
파일 시스템
컴퓨터 파일과 데이터를 organzing 하고 hierarcichal하게 함
hierarchical하게 만들어서 체계적이고 파일을 찾기도 쉬움
데이터 스토리지 디바이스를 사용할 수 있음 (하드디스크, CD ROM, 마그네틱 테이프 등)
적어도 외형적으로는 통일된 파일 시스템이 들어갈 수 있게 만듦
파일 시스템을 엑세스하기 위한 시스템콜은 기본적으로 왼쪽에 있는 9개가 다임
9개 외에도 더 다양한 용도의 시스템콜이 있지만 기본적으로는 이 아홉개를 씀
유저 프로그램이 이 시스템콜을 사용해서 파일을 엑세스 함
시스템콜이 발생할 때마다 소프트웨어 인터럽트인 트랩이 발생함
snnchallenge.tistory.com/112?category=903783
유저가 시스템콜로 파일을 엑세스하기 위한 시스템콜을 부르면
파일 시스템 매니지먼트가 있고, 하드웨어 컨트롤러로 하드웨어를 컨트롤함
디스크 등은 block device고, 키보드, 스크린, 프린터 등은 character device 임
character device는 단위가 1 byte라서 중간에 버퍼가 필요없음
block device는 단위가 1 block임. 1 block은 보통 4 Kbyte = 4096 byte임. 버퍼캐시가 있음
UNIX file access primitives
open은 파일을 열 때 사용
(read, write를 하기 위해서 파일을 open 해야 함, 새로 만들면서 open 하기도 함)
create는 없는 파일을 empty file로 새로 만들 때 사용
close는 open한 파일을 close할 때 사용
read는 open한 파일을 읽어들일 때 사용
write는 open한 파일에 데이터를 쓸 때 사용
lseek는 랜덤 엑세스가 되는 디바이스인 block device 디스크에서만 사용하는 시스템콜임
(파일은 바이트 단위로 addressible한데, 바이트마다 주소가 있음
해당 바이트만 콕 찝어내는, 위치를 이동시키는 데 사용)
unlink와 remove는 같은 시스템콜, 파일을 지우는 데 사용
fcntl은 파일에 관한 attribute를 변경시키거나 읽을 때 사용
이 시스템콜은 ANSI C. 국제표준이 아니라 미국 국립 표준 국에서 표준화한 거임
이 함수들은 unbuffered IO, 커널에 있는 그 버퍼가 아니라 라이브러리안에 있는 버퍼가 없다는 말임.
유저 메모리에 있는 버퍼가 없다는 말임
파일디스크립터
파일을 open 하면, open할 때 넘어오는 포인터가 있음
파일을 지정하는 번호인데, 이를 파일디스크립터라고 함
파일디스크립터는 0,1,2,3...으로 음수가 아닌 정수로 주어짐
파일을 새로 만들어서 open하거나 기존에 있는 파일을 open 할 때, 파일디스크립터로 read write 함
유닉스에서 프로세스를 만들면 기본적으로 세 개의 파일디스크립터가 만들어짐
0은 표준 입력으로 대개가 키보드
1은 표준출력, 2는 표준에러인데 둘다 스크린임
둘다 스크린으로 같은데 output과 error를 구분해야할 때가 있어서 굳이 구분을 하는 거임
이 상태에서 어떤 파일을 오픈하면 그 파일디스크립터는 3번이 됨
사용되지 않은 정수 중 가장 낮은 숫자가 반환되는 거임
/* a rudimentary example program */
/* these header files are discussed below */
#include <fcntl.h>
#include <unistd.h>
main()
{
int fd;
ssize_t nread;
char buf[1024];
/* open file “data” for reading */
fd = open(“data”, O_RDONLY);
/* read in the data */
nread = read(fd, buf, 1024);
/* close the file */
close(fd);
}
fd = open("data", O_RDONLY)
첫번째 인자에 들어가 있는 건 relative pathname임
O_RDONLY는 읽기 전용으로 읽으라는 말임
fd는 3이 됨
nread = read(fd, buf, 1024)
첫번째 인자는 파일디스크립터이고,
그 파일디스크립터가 가리키는 파일을 1024만큼 읽어서 두번째 인자인 buf에 넣으라는 말임
nread에는 read작업 후 실제로 읽은 바이트의 수가 들어감
만약 3번 파일에 1024 이상의 충분한 바이트 수가 있다면 nread는 1024가 됨
하지만 100 byte밖에 없으면 100만 읽어서 nread는 100이 될 거임
#include <fcntl.h>
<>라는 건 /usr/include/fcntl.h가 있다는 것을 나타내는 것임
/usr/include가 default directory임. 만약 absolute pathname으로 넣으려면 ""로 해주면 됨
fcntl.h는 open 시스템콜이 들어있음
#include <unistd.h>
ssize_t 타입은 사실 integer인데 복잡하게 ssize_t라는 이름을 붙임
#typedef ssize_t int 이런 명령어가 unistd.h 안에 sys/types.h에 저장되어 있음
이 ssize_t는 primitive system data type이라고 함
유닉스에 버전이 너무 많다보니까 read의 return 타입을 short로 쓰기도 하고 long으로 쓰기도 했음
너무 제각각이라서 표준화를 하려다보니 이름을 하나로 통일한 거임
다른 버전에서는 #typedef ssize_t short로 써도 그 속성을 숨기는 거임
'CS > 유닉스프로그래밍' 카테고리의 다른 글
3-2. 유닉스 파일 엑세스, 파일 시스템, permission (0) | 2020.10.07 |
---|---|
3-1. 유닉스 파일 : redirection, 표준 IO 라이브러리, error handling (0) | 2020.10.06 |
2-2. 유닉스 파일 시스템콜 : open, creat, close, read, write, lseek , dup, fcntl (1) | 2020.10.06 |
1. 유닉스 기본 개념 (0) | 2020.09.13 |
0. 유닉스 역사 (0) | 2020.09.13 |