c언어/시스템 프로그래밍

시스템 프로그래밍 3일차

시스템 엔지니어 2023. 3. 31. 14:49

시스템 프로그래밍 3일차

유튜브 강의 참고

File read & write

read

$ man -s 2 read
#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

fd (file descriptor)

  • 읽으려는 파일의 file descriptor

buf (buffer)

  • 읽은 내용을 저장할 buffer의 시작 주소

count

  • 읽을 byte

Return

  • 0: 파일의 끝(EOF)에 도달, -1: 에러

write

$ man -s 2 write
#include <unistd.h>

# const 수정이 불가
ssize_t write(int fd, const void *buf, size_t count);

fd (file descriptor)

  • 기록하려는 파일의 descriptor

buf (buffer)

  • 기록할 내용이 저장된 buffer의 시작 주소

count

  • 기록할 byte

return: 실제로 기록한 byte 수

  • -1: 에러

File offset

  • File operation (read/write)를 적용할 위치
  • 파일의 시작점부터 현재 위치까지의 byte 수
  • Read(2)/write(2) 수행 시, 읽은/기록한 byte 수 만큼 순차적으로 이동

read write 실습

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(void) {
  int rfd, wfd, n;
  char buf[10];

  rfd = open("hello.txt", O_RDONLY);
  if(rfd == -1) {
          perror("Open hello.txt");
          exit(1);
  }

  wfd = open("hello.bak", O_CREAT | O_WRONLY | O_TRUNC, 0644);
  if (wfd == -1) {
          perror("Open hello.bak");
          exit(1);
  }

  while ((n = read(rfd, buf, 6)) > 0){
          if (write(wfd, buf, n) != n) perror("Write");
          printf("%d", n);
  }

  if (n == -1) perror("Read");

  close(rfd);
  close(wfd);
  return 0;
}
# hello.txt 생성
root@test-ubuntu:~/test/2-3# echo "Hello system programming" > hello.txt
# hello.bak 파일 없는거 확인
root@test-ubuntu:~/test/2-3# cat hello.bak
cat: hello.bak: No such file or directory
# 실행파일 실행
root@test-ubuntu:~/test/2-3# ./read_write.out 
# hello.txt 가 백업 된 것을 확인
root@test-ubuntu:~/test/2-3# cat hello.bak 
Hello system programming

File access methods

순차 접근 (Sequential access)

  • File을 record(or bytes) 단위로 순서대로 접근
  • fgetc()

직접 접근 (Directed access)

  • 원하는 Block를 직접 접근
  • lseek(), seek()

lseek (직접 접근)

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

fd (file descriptor)

  • 대상 file descriptoroffset
  • 이동시킬 byte 수 (양수 or 음수)whence
  • 기준 위치Return: 이동후 file offset
  • -1: 에러

whence

  • SEEK_SET: 파일 시작
  • SEEK_CUR: 현재 위치
  • SEEK_END: 파일의 끝

사용 예

lseek(fd, 5, SEEK_SET);
  • 파일 시작에서 5번째 byte로 이동
  • lseek(fd, 0, SEEK_END);
  • 파일 끝으로 이동
  • cur_offset = lseek(fd, 0, SEEK_CUR);
  • 내 현재 위치

file offset 실습

#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(void) {
  int fd, n;
  off_t start, cur;
  char buf[256];

  fd = open("linux.txt", O_RDONLY);
  if (fd == -1) {
          perror("Open linux.txt");
          exit(1);
  }

  start = lseek(fd, 0, SEEK_CUR);     // 현재 위치 저장
  n = read(fd, buf, 255);             // 0 byte에서 255 byte 까지 저장
  buf[n] = '\0';                      // `\0`는 문자열 마지막 의미
  printf("offset start=%d, Read Str=%s, n=%d\n", (int)start, buf, n);    // 현재 위치 start 출력, Str 출력, 남은 byte수 출력
  cur = lseek(fd, 0, SEEK_CUR);
  printf("offset cur=%d\n", (int)cur);

  start = lseek(fd, 6, SEEK_SET); // 6번째 byte로 이동
  n = read(fd, buf, 255);         // 6번째 byte에서 255 바이트까지 읽기
  buf[n] = '\0';                  // `\0`는 문자열 마지막 의미
  printf("Offset start=%d, Read Str=%s", (int)start, buf);        // 현재 위치 start 출력, Str 출력, 남은 byte수 출력

  close(fd);

  return 0;
}
# linux.txt 생성
root@test-ubuntu:~/test/2-3_seek# echo "Linux System Programming" > linux.txt
# 실행파일 실행
root@test-ubuntu:~/test/2-3_seek# ./seek.out 
# 출력
offset start=0, Read Str=Linux System Programming
, n=25
offset cur=25
Offset start=6, Read Str=System Programming

Page cache & write-Back

Page cache

  • In-memory store of recently accessed data from an on-disk filesystem
  • disk 접근 시간 절약을 위해 kernel 내부적 기법

Page write-back

  • Page cache에 변경 된 내용을 disk에 반영하는 것
  • 반영 시기는 kernel이 결정

fsync

#include <unistd.h>
int fsync(int fd);

Page write-back을 강제로 수행

fd (file descriptor)
  • fd (file descriptor)
    Return
  • 0: success
  • -1: error