write 함수

union·2020년 12월 22일

C Programming

목록 보기
1/3

1. write()란?

파일의 내용에 새로운 데이터를 저장할 수 있으며, 수정, 덧붙이기 등 필요한 작업을 수행할 시 사용되는 함수이다.

ssize_t write(int fd, const void *buf, size_t nbytes);
  • fd : 데이터 전송 영역을 나타내는 파일 디스크립터
  • buf : 전송할 데이터를 가지고 있는 버퍼의 포인터
  • nbytes : 전송할 데이터의 byte 수
  • 정상적으로 읽기를 했다면 읽은 byte의 개수를, 실패 시 -1 반환

설명

write함수의 인자로 데이터를 쓸 파일의 파일 디스크립터, 데이터를 담고 있는 버퍼, 파일에 기록할 byte 수를 정하는 nbytes가 있다. 즉, 파일 디스크립터에 버퍼에 포함된 데이터를 nbytes만큼 기록한다고 할 수 있다.

writer 함수가 호출되고 리턴되었을 때,buf에 담겨있던 데이터가 물리적인 파일에 바로 저장될까?

"아닐 수도 있다"
write함수는 디스크에 데이터가 저장되는 것을 보장해주지 않는다.

write 함수가 리턴된 이후에도 디스크에 데이터가 저장이 안 된다면 언제 저장이 될까?

2. write()의 동작

write 함수는 OS에서 제공하는 함수가 아니라 C 표준 라이브러리에서 제공하는 wrapper함수로, 사용자가 OS가 제공하는 기능을 사용하기 쉽게 만든 함수이다.

2.1 사용자 영역과 커널 영역

사용자 영역은 사용자 프로세스가 접근할 수 있는 메모리 영역이다.
우리가 코드에 write 함수를 호출한다면 그것은 사용자 영역에서 호출한 것이다. 우리가 write에 넘긴 buf도 사용자 영역에 존재하는 데이터다.

커널 영역은 OS가 접근할 수 있는 메모리 영역이다.
OS가 하드웨어를 직접적으로 다루기 때문에 커널 영역에 존재하는 데이터는 하드웨어와 밀접한 관련이 있다. 파일이 저장되어 있는 디스크도 커널 영역에서만 접근이 가능하다.

메모리에서 사용자 영역과 커널 영역을 분리한 이유는 무엇일까?
사용자 프로세스가 하드웨어와 같은 운영체제의 중요한 자원에 마음대로 접근할 수 없도록 하기 위해서이다.

2.2 지연된 쓰기

사용자 영역의 프로그램이 write함수를 호출하면 사용자 영역의 버퍼에 저장된 데이터가 커널 영역의 버퍼로 복사된다. 커널 영역의 버퍼에 데이터를 옮겨서 데이터를 디스크에 저장하기 위해서이다.
디스크에 데이터를 쓰는 작업이 함수 호출 시간에 비해 오래걸리기 때문에 OS는 write함수의 호출이 끝나기 전에 데이터를 디스크에 저장하지 않는다.
매번 write 함수를 호출할 때마다 디스크에 데이터가 기록되기를 기다리면 프로그램의 성능이 떨어져 OS는 디스크에 기록할 필요가 있는 버퍼에 따로 표시만 하고 디스크에 기록하지 않는다. OS는 나중에 디스크에 기록할 필요가 있는 버퍼를 모아 한번에 디스크에 기록한다. 이 작업을 Delayed write 라고 한다.

만약 write함수를 통해 데이터를 썼지만 아직 디스크에 기록되지 않는 파일을 read 함수를 이용해 읽는다면 어떻게 될까?

OS는 디스크에 접근하여 데이터를 읽지 않고 버퍼에 저장된 데이터를 읽는다.
디스크에 접근하지 않고 읽기 작업을 수행하여 읽기 성능이 향상된다. 어떤 프로그램이 쓰기와 읽기 작업을 번갈아 수행한다면 디스크에는 데이터가 기록되지 않은 상태에서 버퍼에 저장된 데이터만 사용된다.

하지만 지연된 쓰기 방식엔 문제점이 있다.

  1. 디스크에 기록되는 순서가 write함수를 호출한 순서와 달라질 수 있다. 운영체제가 디스크에 데이터를 기록할 때 최적화를 수행하기 때문에 디스크에 데이터가 기록되는 순서가 프로그램이 write 함수를 이용해 파일에 데이터를 기록한 순서와 달라질 가능성이 잇다.
  2. 아직 디스크에 데이터를 기록하지 않은 상태에서 시스템이 종료되거나 디스크 오류가 발생할 수 있다.

0개의 댓글