2011. 9. 3. 22:35
재시작 라이브러리(restart library)는 순간적인 사건으로 요청한 작업을 완료하지 못했을 경우 스스로 재시작할 수 있는 함수들의 집합이다.
재시작 라이브러리는 시그널에 의한 중단과 불완전한 I/O 두 부분에 중점을 두고 있다. 예를 들어 read, write와 같은 라이브러리 함수들은 I/O 명령을 완전히 실행하기 전에 시그널에 의해 중단될 때 -1을 리턴하고, errno를 EINTR로 설정한다.
이러한 중단은 실제로 에러 상황이 아닌 프로그램이 블로킹 I/O를 사용할 때 시그널의 처리를 위한 자연스러운 사건이다. 함수가 -1을 리턴하고, errno가 EINTR로 설정된 경우 재시작 함수는 재시작 과정을 수행한다. |
[ restart.c ] |
#include <errno.h> #include <fcntl.h> #include <limits.h> #include <string.h> #include <sys/select.h> #include <sys/time.h> #include <sys/wait.h> #include "restart.h" #define BLKSIZE PIPE_BUF #define MILLION 1000000L #define D_MILLION 1000000.0 /* Private functions */ static int gettimeout(struct timeval end, struct timeval *timeoutp) { gettimeofday(timeoutp, NULL); timeoutp->tv_sec = end.tv_sec - timeoutp->tv_sec; timeoutp->tv_usec = end.tv_usec - timeoutp->tv_usec; if (timeoutp->tv_usec >= MILLION) { timeoutp->tv_sec++; timeoutp->tv_usec -= MILLION; } if (timeoutp->tv_usec < 0) { timeoutp->tv_sec--; timeoutp->tv_usec += MILLION; } if ((timeoutp->tv_sec < 0) || ((timeoutp->tv_sec == 0) && (timeoutp->tv_usec == 0))) { errno = ETIME; return -1; } return 0; } /* Restart versions of traditional functions */ int r_close(int fildes) { int retval; while (retval = close(fildes), retval == -1 && errno == EINTR) ; return retval; } int r_dup2(int fildes, int fildes2) { int retval; while (retval = dup2(fildes, fildes2), retval == -1 && errno == EINTR) ; return retval; } int r_open2(const char *path, int oflag) { int retval; while (retval = open(path, oflag), retval == -1 && errno == EINTR) ; return retval; } int r_open3(const char *path, int oflag, mode_t mode) { int retval; while (retval = open(path, oflag, mode), retval == -1 && errno == EINTR) ; return retval; } ssize_t r_read(int fd, void *buf, size_t size) { ssize_t retval; while (retval = read(fd, buf, size), retval == -1 && errno == EINTR) ; return retval; } pid_t r_wait(int *stat_loc) { pid_t retval; while (((retval = wait(stat_loc)) == -1) && (errno == EINTR)) ; return retval; } pid_t r_waitpid(pid_t pid, int *stat_loc, int options) { pid_t retval; while (((retval = waitpid(pid, stat_loc, options)) == -1) && (errno == EINTR)) ; return retval; } ssize_t r_write(int fd, void *buf, size_t size) { char *bufp; size_t bytestowrite; ssize_t byteswritten; size_t totalbytes; for (bufp = buf, bytestowrite = size, totalbytes = 0; bytestowrite > 0; bufp += byteswritten, bytestowrite -= byteswritten) { byteswritten = write(fd, bufp, bytestowrite); if ((byteswritten == -1) && (errno != EINTR)) return -1; if (byteswritten == -1) byteswritten = 0; totalbytes += byteswritten; } return totalbytes; } /* Utility functions */ struct timeval add2currenttime(double seconds) { struct timeval newtime; gettimeofday(&newtime, NULL); newtime.tv_sec += (int)seconds; newtime.tv_usec += (int)((seconds - (int)seconds)*D_MILLION + 0.5); if (newtime.tv_usec >= MILLION) { newtime.tv_sec++; newtime.tv_usec -= MILLION; } return newtime; } int copyfile(int fromfd, int tofd) { int bytesread; int totalbytes = 0; while ((bytesread = readwrite(fromfd, tofd)) > 0) totalbytes += bytesread; return totalbytes; } ssize_t readblock(int fd, void *buf, size_t size) { char *bufp; ssize_t bytesread; size_t bytestoread; size_t totalbytes; for (bufp = buf, bytestoread = size, totalbytes = 0; bytestoread > 0; bufp += bytesread, bytestoread -= bytesread) { bytesread = read(fd, bufp, bytestoread); if ((bytesread == 0) && (totalbytes == 0)) return 0; if (bytesread == 0) { errno = EINVAL; return -1; } if ((bytesread) == -1 && (errno != EINTR)) return -1; if (bytesread == -1) bytesread = 0; totalbytes += bytesread; } return totalbytes; } int readline(int fd, char *buf, int nbytes) { int numread = 0; int returnval; while (numread < nbytes - 1) { returnval = read(fd, buf + numread, 1); if ((returnval == -1) && (errno == EINTR)) continue; if ((returnval == 0) && (numread == 0)) return 0; if (returnval == 0) break; if (returnval == -1) return -1; numread++; if (buf[numread-1] == '\n') { buf[numread] = '\0'; return numread; } } errno = EINVAL; return -1; } ssize_t readtimed(int fd, void *buf, size_t nbyte, double seconds) { struct timeval timedone; timedone = add2currenttime(seconds); if (waitfdtimed(fd, timedone) == -1) return (ssize_t)(-1); return r_read(fd, buf, nbyte); } int readwrite(int fromfd, int tofd) { char buf[BLKSIZE]; int bytesread; if ((bytesread = r_read(fromfd, buf, BLKSIZE)) < 0) return -1; if (bytesread == 0) return 0; if (r_write(tofd, buf, bytesread) < 0) return -1; return bytesread; } int readwriteblock(int fromfd, int tofd, char *buf, int size) { int bytesread; bytesread = readblock(fromfd, buf, size); if (bytesread != size) /* can only be 0 or -1 */ return bytesread; return r_write(tofd, buf, size); } int waitfdtimed(int fd, struct timeval end) { fd_set readset; int retval; struct timeval timeout; if ((fd < 0) || (fd >= FD_SETSIZE)) { errno = EINVAL; return -1; } FD_ZERO(&readset); FD_SET(fd, &readset); if (gettimeout(end, &timeout) == -1) return -1; while (((retval = select(fd+1, &readset, NULL, NULL, &timeout)) == -1) && (errno == EINTR)) { if (gettimeout(end, &timeout) == -1) return -1; FD_ZERO(&readset); FD_SET(fd, &readset); } if (retval == 0) { errno = ETIME; return -1; } if (retval == -1) return -1; return 0; } |
[ restart.h ] |
#ifndef __RESTART_H_ #define __RESTART_H_ #include <fcntl.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #ifndef ETIME #define ETIME ETIMEDOUT #endif struct timeval add2currenttime(double seconds); int copyfile(int fromfd, int tofd); int r_close(int fildes); int r_dup2(int fildes, int fildes2); int r_open2(const char *path, int oflag); int r_open3(const char *path, int oflag, mode_t mode); ssize_t r_read(int fd, void *buf, size_t size); pid_t r_wait(int *stat_loc); pid_t r_waitpid(pid_t pid, int *stat_loc, int options); ssize_t r_write(int fd, void *buf, size_t size); ssize_t readblock(int fd, void *buf, size_t size); int readline(int fd, char *buf, int nbytes); ssize_t readtimed(int fd, void *buf, size_t nbyte, double seconds); int readwrite(int fromfd, int tofd); int readwriteblock(int fromfd, int tofd, char *buf, int size); int waitfdtimed(int fd, struct timeval end); #endif /* __RESTART_H_ */ |
'예제 코드 & 코드 조각' 카테고리의 다른 글
[string.c] strcat, strcpy, strcmp, strlen (1) | 2011.10.14 |
---|---|
showtimes - exit핸들러 등록하여 프로그램 CPU 사용률 출력 (0) | 2011.09.03 |
keeplog - 리스트 자료 구조를 사용하여 커맨드 실행 기록 저장 (0) | 2011.09.02 |
wordaverage - 한 줄 평균 단어 구하기 (0) | 2011.09.02 |
makeargv - 인자 배열 만들기 (0) | 2011.09.02 |