일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 동기 함수 내에서 비동기 함수 호출
- @published 프로퍼티 래퍼
- BFS
- CSS
- react-router-dom
- 블로그업로드확인
- modal 관리
- react상태관리라이브러리
- react hook
- react fsd
- 반응형 css
- 리렌더링최적화
- LazyVGrid
- featured-sliced-design
- 페이지전환
- 컴퓨터네트워크
- react modal
- 세로모드끄기
- 가로모드끄기
- GridItem
- LazyHGrid
- zustand란
- 리액트최적화
- @observedobject 프로퍼티 래퍼
- 페이지이동함수
- 비동기함수
- navigationBar 숨기기
- @environmentobject 프로퍼티 래퍼
- zustand
- C++
- Today
- Total
leebaek
[UNIX프로그래밍] 4강 - 파일 입출력 본문
- UNIX file 접근 primtives
- file descriptor
- open 시스템 호출
- create 시스템 호출
- close 시스템 호출
- read 시스템 호출
- write 시스템 호출
- read/write의 효율성
- lseek와 임의 접근
- file의 제거
- 표준 입력, 표준 출력, 표준 오류
- 표준 입출력의 변경
- 오류메세지 출력
■ UNIX file 접근 primitivies
□ file : byte들의 linear sequence
□ 파일 입출력
- 저수준 파일 입출력 ( open, close, read, write, dup, dup2, fcntl, lseek, fsync )
- 고수준 파일 입출력 ( fopen, fclose, fread, fwrite, fputs, fgets, fprintf, fscanf, freopen, fseek )
> 열린 파일을 참조할 때
저수준 파일 입출력은 file descriptor 사용
고수준 파일 입출력은 file pointer 사용
■ file descriptor
: 현재 open된 file을 구분할 목적으로 UNIX가 붙여 놓은 번호
□ 표준 입출력 ( 정수 )
- 0 : 표준 입력
- 1 : 표준 출력
- 2 : 표준 오류 출력
- 한 프로세스가 동시에 open 할 수 있는 file의 개수 제한 -> close 사용
■ open 시스템 호출 ( 기존의 file 열기 or 새로운 file 생성 후 열기 )
□ 파일 열기 ( return 값 file descriptor : 성공 | -1 : 실패 )
> 헤더 파일
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *filename, int oflag, [mode_t model]);
int fd1, fd2, fd3;
// 쓰기 전용으로 열 때 ( 파일이 있는 경우 )
fd1 = open("test.txt", O_WRONLY | O_TRUNC );
// 쓰기 전용으로 열 때 ( 파일이 없는 경우 )
fd2 = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC );
// 읽기 + 쓰기 + 추가용으로 열 때
fd3 = open("test.txt", O_RDWR | O_APPEND );
flag : 파일의 상태를 조정
mode : 파일의 접근 권한 설정 ( 파일을 생성할 때만 사용 )
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
// 0600, 0644, 0664 도 가능
■ creat 시스템 호출 ( 기존의 file 열기 or 새로운 file 생성 후 열기 )
□ 파일 열기 ( return 값 file descriptor : 성공 | -1 : 실패 )
- file을 쓰기 가능한 상태로 open ( flag : WONLY 와 같음 )
- file이 이미 존재하면 mode는 무시 ( 기존 file은 0으로 open )
파일 생성 기능이 없던 구 버전 유닉스에서 사용하던 시스템 콜로, 읽기 전용 open()과 같은 의미
> 헤더 파일
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char *filename, mode_t mode);
■ close 시스템 호출 ( open된 file을 닫을 때 사용 )
□ 파일 닫기 ( return 값 0 : 성공 | -1 : 실패 )
- process 종료 시 open된 file들은 자동으로 close됨
- 동시에 open할 수 있는 file 수 제한 때문에 close 사용
> 헤더 파일
#include <unistd.h>
int close(int filedes); // filedes : open된 file의 descriptor
close(fd);
■ read 시스템 호출 ( open된 file로 부터 지정 byte수 만큼의 data를 읽어 지정된 저장장소에 저장 )
□ 파일 읽기 ( return 값 실제로 읽은 byte수 : 성공 | -1 : 실패 )
- 처음은 파일의 시작, read() 함수를 실행할 때마다 읽은 크기만큼 오프셋 이동
- return 값 < nbytes : file에 남은 data가 nbytes보다 적을 때
> 헤더 파일
#include <unistd.h>
sszie_t read(int filedes, void *buffer, size_t nbytes); // filedes : open된 file descriptor
buffer : 읽은 data를 저장할 곳의 주소
- data type은 상관없음 ( 내가 원하는 타입을 지정 하면 됨 )
nbytes : 읽을 byte 수
- 데이터 타입 상관없이 byte 단위로 읽음
■ write시스템 호출 ( 지정된 저장장소에서 지정한 byte수 만큼의 data를 읽어 open된 file에 씀 )
□ 파일 쓰기 ( return 값 쓰여진 byte수 : 성공 | -1 : 실패 )
- return 값 < nbytes : 쓰는 도중 파일에 쓸 공간 없음 : 1 리턴 / 쓰기 전에 꽉차면 -1 리턴
> 헤더 파일
#include <unistd.h>
ssize_t write(int filedes, const void *buffer, size_t nbytes);
rfd = open("linux.txt", O_RDONLY);
wfd = open("linux.txt", O_CREATE | O_WRONLY |O_TRUNC, 0644);
while( (n=read(rfd, buf, 6)) > 6 ) {
if ( write(wfd, buf, n) != n ) perror("Wtire");
}
■ read / write의 효율성
□ File을 copy하는 프로그램의 실행 시간
- BUFSIZE가 512 ( disk blocking factor )의 배수 일 때, 효율적
- system call의 수가 적을수록 효율적
-> 작은 크기의 버퍼를 사용하면 시스템 호출의 빈도가 증가하고, 디스크 접근이 잦아져 성능이 저하됨
-> 너무 큰 버퍼를 사용하면 메모리 낭비와 캐시 효율성 문제가 발생함 )
disk blocking factor : 데이터를 읽고 쓸 때 사용하는 블록 크기 의미
■ lseek 시스템 호출 ( open된 file 내의 특정 위치로 file pointer 이동 )
□ file pointer 이동 ( return 값 이동된 위치(시작점부터의 위치) : 성공 | -1 : 실패 )
> 헤더 파일
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
whence (기준점) : whence에서 offset 만큼 떨어진 위치로 이동
- SEEK_SET : file 시작 지점
- SEEK_CUR : 현재 file의 위치
- SEEK_END : file의 끝 지점 ( *마지막 데이터 위치 + 1* )
offset : +/-로 방향 설정 가능
// 실습 문제
int main() {
char ch = 'X';
int i, fd;
fd = open("data1", O_WRONLY|O_CREAT, 0600); // (a)읽기쓰기 가능한 "data1" file을 생성하고, 문자 ‘X'를 10개 씁니다.
for ( i = 0; i < 10; i++ ){
write(fd, &ch, 1);
}
lseek(fd, 0, SEEK_SET); // (b) "data1" file의 첫 번째 위치로 file pointer를 옮긴 후 문자 ‘Y'를 하나 씁니다.
write(fd, "Y", 1);
lseek(fd, 0, SEEK_END); // (c) "data1" file의 마지막 문자 다음 위치로 file pointer를 옮긴 후 문자 ‘Y'를 하나 씁니다.
write(fd, "Y", 1);
for ( i = 1; i < 8; i += 2 ) {
lseek(fd, i, SEEK_SET); // (d) "data1" file의 2, 4, 6, 8번째 문자를 ‘Z'로 바꾸어 씁니다.
write(fd, "Z", 1);
}
lseek(fd, 14, SEEK_SET); // (e) "data1" file의 15번째 위치에 문자 ‘T'를 씁니다.
write(fd, "T", 1);
lseek(fd, -2, SEEK_END); // (f) "data1" file의 뒤에서 2번째 위치에 문자 ‘S'를 씁니다.
write(fd, "S", 1);
lseek(fd, -2, SEEK_CUR); // (g) 'S' 바로 앞에 문자 ‘W'를 씁니다.
write(fd, "W", 1);
return 0;
}
// 결과 : YZXZXZXZXXYWST
■ file의 제거 ( file을 삭제 )
- 헤더 파일이 다름
- file descriptor가 아니라, file name 씀
□ unlink ( return 값 0 : 성공 | -1 : 실패 )
- 파일의 hard link를 삭제 -> 다 삭제하면 파일 오픈 불가능 ( free block으로 이동 )
> 헤더 파일
#include <unistd.h>
int unlink(const char *filename);
□ remove ( return 값 0 : 성공 | -1 : 실패 )
> 헤더 파일
#include <stdio.h>
int remove(const char *filename)
file이 open 되어 있는 상태에서 file을 삭제하면 ?
- 파일을 닫기 전에 파일을 쓸 수 있고, 읽을 수도 있음
-> 파일은 지워졌지만, 파일 테이블 구조체 배열에 파일에 대한 정보(파일 포인터)가 저장되기 때문에 액세스 가능
차이점 : unlink는 file만 삭제, remove는 file과 빈 directory도 삭제
■ 표준 입력, 표준 출력, 표준 오류
- 표준 입력(키보드) : fd = 0
- 표준 출력(터미널 화면) : fd = 1
- 표준 오류(터미널 화면): fd = 2
-> 출력 두가지, 2는 주로 테스트할 때 사용
■ 표준 입출력의 변경
redirection :
$ ./a.out < infile ( 입력 )
$ ./a.out > outfile ( 출력 )
$ ./a.out < infile > outfile
pipe :
a.out1의 표준 출력이 a.aout2의 표준 입력으로
$ ./a.out1 | ./a.out2
■ 오류 메시지 출력
perror("error .. ");
'수업 정리 > UNIX 프로그래밍' 카테고리의 다른 글
[UNIX프로그래밍] 6강 - 프로세스 정보 (7) | 2024.10.16 |
---|---|
[UNIX프로그래밍] 5강 - 시스템 정보 (1) | 2024.10.15 |
[UNIX프로그래밍] 3강 - File 다루기 (0) | 2024.10.12 |
[UNIX프로그래밍] 2강 - Directory 다루기 (0) | 2024.10.12 |
[UNIX프로그래밍] 1강 - UNIX 명령어 및 Vi 에디터 사용법 (1) | 2024.10.01 |