write()로 쓰기
1 2 3 | #include <stdio.h> ssize_t write(int fd, const void *buf, size_t count); | cs |
코드를 보면 알 수 있듯이 반환값은 ssize_t 형이다. (이에 대해서는 이전 포스팅에서 이미 설명을 했었다.) write() 호출은 count 바이트만큼 파일 디스크립터(fd)가 참조하는 파일의 현재 파일 위치에 시작 지점이 buf인 내용을 기록한다. 파일 디스크립터가 표현하는 객체에 탐색하는 기능이 없다면, 쓰기 작업은 기본적으로 항상 파일의 처음 위치에서 시작한다.
write() 호출에 성공하면 쓰기에 성공한 바이트 수(ssize_t)를 반환한다. 더불어 파일 오프셋도 반환한 바이트 수만큼 앞으로 나아간다. 이전 포스팅들에서 다루었던 다른 시스템 콜들과 마찬가지로 write() 시스템 콜 또한 에러가 발생하면 -1을 반환하고, errno를 상황에 따라 적절한 값으로 설정한다. 0을 호출할 경우에는 별 의미 없으며, 단순히 0바이트를 썼다는 의미이다. 여담으로 count를 0으로 둔 상태에서 write() 시스템 콜을 호출하면 호출 즉시 0을 반환한다.
write()의 기본적인 사용법을 알아보자.
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 | #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main() { int fd = open("TEXT", O_RDWR | O_CREAT, 0666); if(fd == -1) { fprintf(stderr, "Failed to open file.\n"); exit(0); } const char *buf = "Welcome to VALLHALLA!\n"; // writes buf --> fd ssize_t nr = write(fd, buf, strlen(buf)); if(nr == -1) { fprintf(stderr, "Failed to write file.\n"); exit(0); } else printf("Writing Success!\n"); return 0; } | cs |
TEXT라는 이름의 파일을 일단 열고, 1 buf에 저장되어 있는 문자열 2"Welcome to VALLHALLA!\n"를 파일 디스크립터에 대해 쓰기 작업을 해서 TEXT 파일에 해당 내용을 작성하는 간단한 코드이다. 실행 결과도 같이 한 번 보자.
성공적으로 파일이 생성되고, 거기에 우리가 원하는 문자열이 저장되는 것을 볼 수 있다.
하지만 앞에서 제시한 코드는 언제까지나 write() 시스템 콜 사용법을 알기 위한 '기본적인' 코드인 거지, 효율성을 따진다면 그리 좋지 못하다. 예외가 아직 존재하기 때문이다. 예를 들면 부분 쓰기가 일어나는 상황을 대비하여 코드를 점검해야 할 필요성이 있다.
부분 쓰기
1 2 3 4 5 6 7 8 9 10 | ssize_t ret, nr; while(len != 0 && (ret = write(fd, buf, len)) != 0) { if(ret == -1) { if(errno == EINTR) continue; perror("write"); break; } len -= ret; buf += ret; } | cs |
덧붙이기 모드
1 | int fd = open("TEXT", O_RDWR | O_CREAT | O_APPEND, 0666); | cs |
논블록 쓰기
그 외 에러 코드
에러 코드 |
설명 |
EBADF |
파일 디스크립터가 유효하지 않거나 쓰기 모드가 아니다. |
EFAULT |
buf의 포인터가 호출하는 프로세스 주소 공간 안에 있지 않다. |
EFBIG |
쓰기 작업이 프로세스 단위로 걸려 있는 최대 파일 제약이나 내부 구현 제약보다 더 큰 파일을 만들었다. |
EINVAL |
파일 디스크립터가 쓰기에 적합하지 않은 객체에 매핑되어 있다. |
EIO |
저수준 입출력 에러 |
ENOSPC |
파일 디스크립터가 들어 있는 파일시스템에 공간 부족 |
EPIPE |
파일 디스크립터가 파이프와 소켓에 연결되어 있지만, 반대쪽 읽기 단이 닫혀버렸다. |
'System > System Programming' 카테고리의 다른 글
6. 파일 닫기 - close() (0) | 2019.04.24 |
---|---|
5. 직접 입출력 (0) | 2019.04.24 |
4. 동기식 입출력 - fsync(), fdatasync() (2) | 2019.04.22 |
2. 파일 읽기 - read() (0) | 2019.04.15 |
1. 파일 열기 - open(), creat() (0) | 2019.04.11 |