반응형
write(2)
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
open(2), creat(2), socket(2), accept(2) 등으로 생성한 file descriptor로 데이터 쓰기 또는 전송합니다. 파일에 쓰기를 하면 파일의 쓰기 또는 읽기 위치가 쓴 size만큼 뒤로 이동합니다. write(2)함수는 -1이 return되지 않는 한, 웬만하면 count만큼 정상적으로 write됩니다. O_APPEND flag로 파일을 open했다면 현재 위치가 아닌 항상 파일의 끝에 쓰기가 일어납니다.
파라미터
fd
- open(2), creat(2), socket(2), accept(2) 등을 통하여 정상적으로 open한 file descriptor
buf
- 쓰기를 할 데이터 메모리 영역(buffer)
count
- 쓸 데이터의 size (byte 수)
RETURN
0보다 큰 값
- 실제로 쓴 데이터의 byte 수.
- count와 같은 크기의 값을 return하지만,
count보다 작은 경우에는 signal이 발생하였거나, 쓰기 공간이 부족한경우.
0
- 오류가 발생하지는 않았지만, 파일에 write되지 않음. (count가 0인 경우)
-1
- 오류가 발생한 경우이며 상세한 오류는 errno에 설정됩니다.
EAGAIN : file을 open할 때에 O_NONBLOCK flag이 설정되었으며, 쓰기 상태가 block되었을 때
EAGAIN or EWOULDBLOCK : fd가 socket이고 socket에 O_NONBLOCK으로 설정되었으며,
쓰기가 block되었을 때
EBADF : fd가 유효하지 않은 file descriptor임.
EDESTADDRREQ : fd가 상대주소가 설정되지 않은 Datagram socket인 경우.
즉, connect로 접속된 socket이 아닌경우
EDQUOT : 사용자별로 할당된 file system의 disk quot가 찼을 때.
EFAULT : buf가 access할 수 없는 영역의 데이터 buffer임.
주로 변수를 pointer로 설정한 후에 malloc(3)하지 않은 경우
EFBIG : 파일의 크기가 최대 제한보다 크게 write를 하려고 할 때
EINTR : signal이 발생하여 interrupt됨.
EINVAL : fd, buf, count 등의 변수가 잘못 설정된 경우. (예, count가 -값이 설정된 경우 등)
EIO : I/O 오류. background process에서 terminal에 대한 I/O를 시도했다든 지...
ENOSPC : 저장하려는 공간이 부족한 경우
EISDIR : open된 fd가 directory인 경우
EPIPE : pipe 또는 socket에서 상대 reading end가 close된 경우, SIGPIPE signal이 발생하여야 하는 데,
signal이 ignore하였을 경우 errno에 EPIPE가 설정됨
활용 예제
Sample. 파일 backup
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
/*
* 읽을 데이터를 요청한 사이즈 만큼 읽어들임.
* 파일의 끝이면 요청한 사이즈보다 작을 수 있음.
* Signal이 발생하더라도 읽기를 처리함.
*/
int read_data(int fd, char *buffer, int buf_size)
{
int size = 0;
int len;
while(1) {
if((len = read(fd, &buffer[size], buf_size - size)) > 0) {
size += len;
if(size == buf_size) {
return size;
}
} else if(len == 0) {
return size;
} else {
if(errno == EINTR) {
continue;
} else {
return -1;
}
}
}
}
/*
* 저장할 데이터를 요청한 사이즈 만큼 write함
* signal이 발생하더라도 저장함
*/
int write_data(int fd, const char *buffer, int buf_size)
{
int size = 0;
int len;
while(1) {
if((len = write(fd, &buffer[size], buf_size - size)) > 0) {
size += len;
if(size == buf_size) {
return size;
}
} else if(len == 0) {
return size;
} else {
if(errno == EINTR) {
continue;
} else {
return -1;
}
}
}
}
int main(int argc, char *argv[])
{
int rfd;
int wfd;
int len;
char buffer[4096];
/* 파일을 읽기 전용으로 open함 */
if((rfd = open("sample.txt", O_RDONLY)) == -1) {
fprintf(stderr, "FILE READ OPEN ERROR: %s\n", strerror(errno));
return 1;
}
/* 쓰기 전용으로, 파일이 없으면 생성하고, 파일이 있으면 전체데이터를 삭제하고 open함 */
if((wfd = open("sample.txt.bak", O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) {
fprintf(stderr, "FILE WRITE OPEN ERROR: %s\n", strerror(errno));
return 1;
}
while(1) {
if((len = read_data(rfd, buffer, 4096)) == -1) {
fprintf(stderr, "READ ERROR: %s\n", strerror(errno));
return 1;
}
if(len == 0) {
break;
}
if((len = write_data(wfd, buffer, len)) == -1) {
fprintf(stderr, "WRITE ERROR: %s\n", strerror(errno));
return 1;
}
}
close(rfd);
close(wfd);
return 0;
}
see also: System Call File I/O Library
반응형
'C언어 header > unistd.h' 카테고리의 다른 글
chdir(2) - 현재 작업 디렉토리 변경함 (0) | 2019.10.04 |
---|---|
rmdir(2) - directory 삭제하기 (0) | 2019.10.04 |
read(2) - 파일에서 데이터를 읽기 (0) | 2019.10.04 |
usleep(3) - 설정된 micro초(microsecond: 100만분의 1초) 동안 대기 (0) | 2019.10.01 |
unlink(2) - 파일 삭제 (1) | 2019.10.01 |