학교 강의를 복습하는 차원에서 작성하는 글입니다.
학부생 수준의 글이므로, 오류가 있을 수 있는 점 양해바람니다.
Read
read는 file descriptor로 지정한 파일에서 데이터를 읽는다.
#include <unistd.h>
ssize_t read(int filedes, void * buf, size_t count);
filedes
읽기 작업을 수행할 파일에 대한 기술자 => 숫자를 넣어준다. open 으로 오면, 0을 넣어준다.
buf
파일로부터 읽어 들인 내용을 저장하기 위한 공간
일반적으로 배열을 사용하게 되는데 배열의 데이터 형식은 어느 것이라도 상관없음
=> char dat[100]; int dat[25]; char = malloc[100];
count
읽어들일 파일 내용의 크기를 지정. 바이트 단위
반환값
파일로 부터 읽기 작업이 성공할 경우
=> 읽어 들일 파일 내용의 바이트 크기가 반환
=> 읽어 들일 내용이 없는 경우 0 반환
읽기 작업이 실패한 경우 => -1 반환
int a;
X read(7, &a, 5);
O read(7, &a, 2);
a는 4byte 이므로 //
struct 선언 => 메모리에서 얼마 만큼 쓸 것인지 선언
struct = {
int a; => 4byte
char b[4]; => 4byte
int c; => 4bytr
}
struct d E => 12byte 짜리 E를 생성해라.
write
wirte는 파일 기술자로 지정한 파일로 데이터 저장
#include <unistd.h>
ssize_t write(int filedes, const void * buf, size_t count);
끝에 다다라도, read와 달리 파일 크기가 커지면서 쓴다.
filedes
쓰기 작업을 수행할 파일에 대한 기술자
buf
파일로 쓰려고 하는 내용이 저장되어 있는 공간
일반적으로 배열 사용시 배열의 데이터 형식은 상관 없음
count
buf에 있는 데이터 중 실제로 파일로 저장할 데이터의 크기
반환값
파일로 쓰기가 성공한 데이터의 크기
대부분 count에서 지정한 값과 동일한 값이 반환
count의 값과 반환값이 다르면 쓰기 작업 실패
O_TRUNC / O_APPEND flags
파일 쓰기 위해 여는 경우 open flag 설정
O_WRONLY
기존 파일의 데이터에 덮어 씌움. Read/Wirte pointer는 SEEK_SET / 0 최초 위치
O_WRONLY | O_TUNC
기존 파일을 완전히 지우고 쓰기 모드, Read/Wirte pointer는 SEEK_SET / 0 최초 위치
O_WRONLY | O_APPEND
기존 파일의 맨 뒤에 덧붙임, Read/Wirte pointer는 SEEK_END / 0 맨 마지막 바이트 다음 위치
read/wirte 사용할 수 있는 파일의 개방 상태
read => O_RDONLY
write => O_WRONLY
==> 둘다 O_RDWR
함수 호출의 성공 여부 판단
read
대부분의 경우 세번쨰 인수 count로 지정한 값이 반환
파일의 마지막 부분을 읽을 경우, counter보다 작은 값이 반환
반환 값이 0일 경우 읽기/쓰기 포인터가 EOF(End of File)에 있음
write
모든 경우에서 반환값은 세번째 인수 count로 지정한 값이 반환
반환값이 count로 지정한 값이 아닌 경우 쓰기 작업이 실패
read/write 성공 여부 검사 예제 코드
read는 0 이상의 값을 반환할 때 호출이 성공
0 반환하면 파일의 내용을 읽었기 때문에 더 이상 읽을 것이 없음
if((nread = read(filedes, buf, BUFSIZE)) > 0
wirte는 항상 세번쨰 인수로 지정한 것과 같은 값이 반환되어야 호출이 성공
호출이 실패할 경우 반환값은 세 번쨰 인수의 값보다 작다.
if((Write(filedes, buf, nread) < nread)
EX) 파일 복사 프로그램 cp
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
int main ( int argc, char *argv[] ) # int 는 인자수, char 은 명령어 이름
{
int fdin, fdout; 각각 입출력 역할 파일 기술자 변수 선언
ssize_t nread;
char buffer[5];
if ( argc !=3 ) # argc == 3, argv[0] == ./a.elf argv[1] == a argv[2] == b
{
printf("cp [source file] [dest file]\r\n");
exit(-1);
}
fdin = open(argv[1], O_RDONLY);
fdout = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
/* 정상적으로 읽어 들인 내용이 1바이트 이상인 동안 반복문 수행 */
while((nread = read(fdin, buffer, 5)) > 0)
{
/* write가 비정상적으로 수행되었다. (실패) */
if(write(fdout, buffer, nread) < nread)
{
printf ("File copy failed\r\n");
close(fdin);
close(fdout);
}
}
/* 프로그램이 정상적으로 수행되었다. */
close(fdin);
close(fdout);
}
lseek
지정한 파일에 대해서 읽기/쓰기 포인터의 위치를 임의로 변경
=> 파일의 사이즈를 재는 등에 사용
==> lseek를 seek_end로 보내 크기를 잰다.
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
filedes
읽기/쓰기 포인터를 변경할 파일을 지정
offset
새롭게 지정할 읽기/쓰기 포인터의 위치를 의미
오프셋이기 때문에 기준에 따라 음수도 가능
whence
offset 기준
파일의 맨 처음 SEEK_SET 현재 포인터의 위치 SEEK_CUR 파일의 맨 마지막 SEEK_END 세 가지
반환값
작업이 성공하면 파일의 첫 부분을 ㅣㄱ준으로 한 포인터의 오프셋을 반환
작업이 실패할 경우 off_t -1 이 반환
사용 예
파일의 마지막 바이트로 옮김
newpos = lseek(filedes, (off_t)-1, SEEK_END);
파일의 첫 번째 바이트로 읽기/쓰기 포인터를 옮김
off_t newpos;
newpos = lseek(filedes, (off_t)0, SEEK_SET);
현재 위치에서 뒤로 2바이트만큼 옮김
newpos = lseek(filedes, (off_t)2, SEEK_CUR);
파일의 마지막 바이트 바로 뒤(EOF)로 옮김
newpos = lseek(filedes, (off_t)0, SEEK_END);
lseek 이용 파일 크기 계산 예제
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main( int argc, char argv*[])
{
int filedes;
off_t newpos;
filedes = open(argv[1], O_RDONLY);
/* 읽기/쓰기 포인터를 EOF로 이동한다. */
newpos = lseek(filedes, (off_t)0, SEEK_END);
printf("file size : %d\n", newpos);
}
'프로그래밍 > Linux' 카테고리의 다른 글
[Linux]프로세스 처리 (1) | 2023.10.13 |
---|---|
[Linux]파일입출력(3) (0) | 2023.10.13 |
[Linux]파일입출력(1) (0) | 2023.10.08 |
[Linux]파일시스템 (1) | 2023.10.08 |
[Linux]Debug (0) | 2023.10.08 |