티스토리 뷰

리눅스

리눅스 프로그래밍 파일 다루기

삼전동해커 2021. 9. 22. 18:40

서론

리눅스에서 시스템 호출을 한다는 것은 사용자가 작성한 프로그램에서 요구하는 커널 수준의 서비스를 제공해주는 것이다.

 

파일을 다루기 위한 시스템 호출/표준 함수들

open : 이미 존재하는 파일을 읽기,쓰기 용으로 열거나 새로운 파일을 만듬.

creat : 새로운 파일을 생성하거나 연다.

close : open, creat로 열려진 파일을 닫는다.

read : 열려진 파일로부터 데이터를 읽는다.

write : 열려진 파일에 데이터를 쓴다.

lseek : 파일 안에서 지정한 바이트 위치로 이동.

unlink,remove : 파일 삭제.

 

 

파일 입출력 프로그램 구현.

 

 

파일 디스크립터

파일 디스크립터란 하나의 실행중인 프로그램과 하나의 파일 사이에 연결된 개방 상태라고 할 수 있다.

위에서 본 filedes에는 data.txt를 읽기쓰기 상태로 불러와 파일의 디스크립터 값을 저장한다. 

특정한 파일이 가지고 있는 fd의 실제 값은 커널에 의해 유일하게 설정되기 때문에 하나의 프로그램이 여러 번 다른 파일을 열어도 특정 파일을 다시 불러오는데에 문제가 없다.

또한 fd는 int형으로 선언된다. 

 

읽기/쓰기 포인터

읽기/쓰기 포인터는 fd가 설정된 파일 내에서 읽기/쓰기 작업을 수행할 바이트 단위의 위치를 가리키는 것으로 특정 위치를 기준으로, 상대적 위치를 의미하는 오프셋이다. 프로그램이 파일을 개방한 직후의 읽기/쓰기 포인터는 파일 의 첫 부분을 기준으로 0이라는 값을 가지게 된다.

 

처음엔 파일 내용의 첫 바이트를 가리키게 된다. 이 후 read함수를 이용해 파일의 내용을 읽으면 그 크기만큼 포인터의 위치가 증가한다.

파일의 마지막을 의미하는 EOF를 가리키게 되고, 더 이상 읽을 내용이 없음을 알린다. 포인터는 fd마다 하나씩 존재하면 시스템에 의해 관리된다.

 

두 개의 프로그램이 동일한 설정으로 같을 파일을 열었다 해도, 둘은 다른 포인터를 가지기 때문에 개별적으로 포인터가 관리된다.

 

ex03-01에서 open으로 data.txt를 개방한 후 포인터는 0을 가리키고 있다. 이 후 read함수를 사용해 1024만큼 읽어들인다. 하지만 filedes의 내용이 1024가 안된다. 따라서 data.txt의 크기만큼 nread에 들어가고, 이 값이 포인터의 값이 된다.

 

OPEN

이미 존재하는 파일에 대해 읽기/쓰기를 하기 위해서는 open함수를 호출해야 한다.

 

int open(const char *pathname,int flags, [mode_t mode]);

 

첫 번째 인자 pathname은 개방하려는 파일의 경로명을 가리킨다. 파일의 경로명은 절대경로,상대경로 상관 없다. 변수에 파일 명을 담아도 되고, 포인터로 경로를 지정해도 상관 없다.

 

두 번째 인자 flags는 파일을 개방하고 난 후의 접근 방식을 지정한다.

O_RDONLY : 읽기 방식

O_WRONLY : 쓰기 방식

O_RDWR : 읽기/쓰기 방식

 

세 번째 인자 mode는 파일의 접근 권한을 의미하며 일반적으로는 생략.

 

반환값은 정수형 값을 반환해 이 값이 fd값이 된다. 실패 시엔 -1을 반환.

 

 

CLOSE

open이나 creat로 열린 파일을 닫는데 사용한다. 정확히는 할당 받은 fd값을 반환하는 것이다.

항상 open후에는 close를 해주어야 하지만 예외의 경우가 있다. 파일에 대한 사용이 끝난 후 추가적인 개방 없이 프로그램을 종료하는 경우이다. 프로그램이 종료되면 개방된 파일들이 자동으로 닫히기 때문이다. 

 

open으로 새로운 파일 생성

open함수를 사용해 파일을 열 때, 존재하지 않는 파일을 열면 호출에 실패하게 되고 위 코드에서는 newdata1.txt를 생성할 때 O_CREAT를 사용해 새로운 파일을 생성했다. open("newdata1.txt", O_RDWR | O_CREAT, 0644 )는 newdata1.txt가 있을 경우 읽기쓰기 권한으로 열고 없을 경우 O_CREAT로 새로 만든다는 부분이다.

 

이렇게 파일을 새로 만들고 파일이 이미 존재할 경우 RDWR 권한으로 연다. 이 경우에 이미 존재하는 temp.txt 파일의 내용이 변경될 수 있다. 이를 막기 위해 O_EXCL 플래그를 사용한다.

 

creat

creat함수는 첫 번째 인자에 전달된 위치에 새로운 파일을 생성하고 쓰기 상태로 파일을 연다. 이 때 이미 존재하는 파일을 사용하면 이미 존재하는 파일의 내용이 삭제되는 것에 주의해야 한다.

 

read/write

read 함수는 파일로부터 읽을 내용을 버퍼에 count만큼 읽어오고, 읽어 들인 파일의 바이트 크기만큼 리턴한다. EOF에 다다르면 0을 반환.

write 함수는 파일에 쓸 내용을 count만큼 버퍼에 저장한 후, 쓰기에 성공한 바이트 수만큼 리턴한다. 대부분 count 수만큼 리턴하지만 실패할 경우엔 count와 반환값이 다르다.

이 때 사용되는 버퍼는 void 형을 사용한다. 어떤 데이터 타입을 사용해도 상관없기 때문이다. 하지만 대부분 char형을 사용함.

 

read와 write 함수를 사용한 후 제대로 함수가 사용되었는지 확인하기 위해서 다음과 같이 확인할 수 있다.

 

 

read로 읽어들인 바이트 수가 최소 1바이트 이상인지 확인해 하나라도 읽은 것이 있는지 확인한다. 0이면 EOF에 도달했기 때문에 더 이상 읽을 데이터가 없는 것으로 판단한다.

 

write는 입력할 바이트의 수만큼 입력이 됐는지 리턴값으로 확인한다. 값이 틀리면 원하는 대로 write되지 않은 것이다.

 

O_TRUNC를 사용하는 경우 기존에 존재하던 모든 데이터를 삭제한다. 원치 않을경우 O_APPEND를 사용한다.

 

LSEEK

읽기/쓰기 포인터가 위치할 곳을 정해주는 함수이다. offset 값으로 앞뒤로 이동. 음수가 될 수도 있음.

세 번째 인자로 SEEK_SET은 파일의 맨 처음. SEEK_CUR은 현재 포인터의 위치, SEEK_END은 맨 마지막으로 이동.

작업에 성공할 경우 파일의 첫 부분을 기준으로 한 포인터의 오프셋을 반환한다. 실패할 경우 off_t -1 을 반환.

 

types.h 파일에 off_t 형을 정의되어 있고, unistd.h 파일에 SEEK_SET,SEEK_CUR, SEEK_END가 정의되어 있음.

 

read/write에서 O_APPEND를 사용해 포인터를 맨 뒤로 이동시킬 수 있었는데 LSEEK도 같은 기능을 한다. 하지만  다른 점은 이동할 위치를 임의로 정할수 있다는 점이다. 세 번째 인자를 이용해 포인터의 위치를 정한 후 offset값만큼 떨어진 위치로 포인터를 이동시킨다. 

 

SEEK_SET : 파일의 맨앞으로 포인터 이동.

SEEK_CUR : 현재 포인터의 위치로 이동.

SEEK_END : 파일의 맨 뒤로 이동.

 

위 값중 원하는 위치로 설정한 후, offset값을 조정해 원하는 위치로 설정할 수 있다. 음수로 설정하면 앞으로, 양수로 설정하면 뒤로.

 

SEEK_END를 사용하면 EOF를 시작점으로 한다. 파일의 마지막 바이트에서 +1 위치이다.  따라서 Offset을 -1로 설정해 줘야 한다.

 

unlink/remove

지정한 파일을 삭제한다.

비어있는 디렉토리에 대해서 unlink는 삭제 기능이 없지만, REmove는 비어 있는 디렉토리를 삭제할 수 있다.

하지만 둘다 하위에 다른 디렉토리나 파일이 존재할 경우 삭제할 수  없다.

 

'리눅스' 카테고리의 다른 글

시프밍 수업 정리  (0) 2021.12.19
scp를 이용한 파일 전송  (0) 2020.11.21
mpreferred-stack-boundary=2  (0) 2020.11.14
iptables 설정  (0) 2020.10.25
Linux의 부팅  (0) 2020.10.24
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함