[시스템프로그래밍] 시간과 타이머

2023. 12. 3. 16:27·Study/시스템프로그래밍

POSIX Times

  • 시스템은 Epoch 이후로 경과한 시간을 초 단위로 유지해야
  • Epoch은 세계 표준시 (Coordinated Universal Time, UTC, Greenwich Mean Time 또는 GMT로 불리기도 함) 기준으로 1970년 1월 1일 자정 00:00으로 정의됨
  • POSIX는 구현이 시스템 시간을 실제 시간과 날짜에 어떻게 정렬해야 하는지 명시 X
#include <time.h>
time_t time(time_t *tloc);

 

시스템 시간에 접근한다 (Epoch 이후로 경과한 시간을 초 단위로 표현).

  • tloc: NULL이 아닌 경우, 함수는 시간을 *tloc에 저장
  • time_t: long 형식
  • 성공한 경우, Epoch 이후로 경과한 초의 수 반환
  • 실패한 경우, (time_t)-1 반환
    • → 필수적인 오류는 정의되어 있지 않음
  • 32비트 long 형식의 경우, 1970년 1월 1일부터 약 68년 후인 2038년에 시간이 오버플로될 예정

 

#include <time.h>
double difftime(time_t time1, time_t time0);

두 time_t 형식의 달력 시간 간의 차이를 계산

  • 첫 번째 매개변수에서 두 번째 매개변수를 뺀 값을 담은 double 반환
  • 정의된 오류 X

 

#include <time.h>
char* asctime(const struct tm *timeptr);
char* ctime(const time_t *clock);
struct tm *gmtime(const time_t *timer);
struct tm *localtime(const time_t *timer);

 

localtime()

  • Epoch 이후로 경과한 초를 지정하는 매개변수를 사용
  • 로컬 요구 사항에 맞게 조정된 시간 구성 요소를 포함하는 구조체를 반환

 

 

asctime()

  • localtime에 의해 반환된 구조체를 문자열로 변환

 

 

ctime()

  • asctime(localtime(clock))와 동일
  • 개행 문자로 끝나는 26자 영문자열을 가리키는 포인터를 반환
  • 시간 문자열을 보관하기 위해 정적 저장소를 사용

 

 

gmtime()

  • UTC로 표현된 시간 구성 요소를 포함하는 구조체를 반환

 

 

 

asctime, ctime, localtime은 thread-safe X

  • POSIX: TSF Thread Safe Extension은 스레드 안전한 대안을 지정하며, 추가 버퍼 매개변수를 가짐.

 

struct tm 구조체

  • gmtime 및 localtime 함수에서 사용
  • 구성원 • int tm_sec; /* 초 [0,59] / • int tm_min; / 분 [0,59] / • int tm_hour; / 시 [0,23] / • int tm_mday; / 월의 날짜 [1,31] / • int tm_mon; / 월 [0, 11] / • int tm_year; / 1900년 이후의 연도 / • int tm_wday; / 일요일부터의 일수 [0,6] / • int tm_yday; / 1월 1일부터의 일수 [0, 365] / • int tm_isdst; / 일광 절약 시간(Daylight Saving Time) 플래그 */

 

struct timeval

#include <sys/time.h>
int gettimeofday(struct timeval *restrict tp, void *restrict tzp);
  • struct timeval
    • POSIX:XSI 확장은 이 구조체를 사용하여 미세한 단위의 시간을 표현
    • 구성원 • time_t tv_sec; /* Epoch 이후의 초 / • time_t tv_usec; / 마이크로초 */

 

 

gettimeofday()

  • Epoch 이후의 시간을 초와 마이크로초로 검색
  • tp: 검색한 시간을 받는다.
  • tzp: 역사적인 이유로 반드시 NULL이어야 함
  • 성공하면 0 반환
  • 정의된 오류 없음 (일부 시스템은 고유의 오류를 구현함)
  • long이 32비트인 경우, 최대 지속 시간은 2^31 - 1 마이크로초 또는 약 35분

 

Using real-time clocks

#include <time.h>
int clock_getres(clockid_t clock_id, struct timespec *res);
int clock_gettime(clockid_t clock_id, struct timespec *tp);
int clock_settime(clockid_t clock_id, const struct timespec *tp);
  • Clock
    • 일정 간격으로 증가하는 카운터인 클럭 해상도를 갖고 있는 것
    • POSIX:TMR 타이머 확장에는 clockid_t 유형의 변수로 나타낼 수 있는 클럭이 포함되어 있음
    • 모든 구현은 CLOCK_REALTIME 값에 해당하는 시스템 실시간 클럭을 갖도록 해야 함

 

  • struct timespec 구조체 – time_t tv_sec; /* 초 / – long tv_nsec; / 나노초 */
  • Clock 함수들 – 성공하면 0을 반환하고, 실패하면 -1을 반환하고 errno를 설정함

 

Sleep functions

#include <unistd.h>
unsigned sleep(unsigned seconds);

#include <time.h>
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

sleep()

  • 호출된 스레드를 지정된 시간(초)이 경과하거나 호출된 스레드가 신호를 받을 때까지 중단시킴
  • 요청한 시간이 경과하면 0을 반환
  • 중단되었을 경우 남은 시간을 반환함

 

 

nanosleep()

  • 호출된 스레드를 rqtp에 지정된 시간 간격이 경과하거나 스레드가 신호를 받을 때까지 실행을 중단시킴
  • rmtp가 NULL이 아닌 경우 남은 시간이 포함됨
  • 성공하면 0을 반환하고, 실패하면 -1을 반환하고 errno를 설정함
  • SIGALRM을 포함한 어떤 신호의 사용에도 영향을 미치지 않음

 

POSIX:XSI Interval Timer

 

타이머

  • 컴퓨터 시스템은 일반적으로 소수의 하드웨어 간격 타이머를 가지고 있음

 

Clock vs. timer ?

  • 운영 체제는 이러한 하드웨어 타이머를 사용하여 여러 소프트웨어 타이머를 구현
    • 타임 쉐어링 운영 체제는 프로세스 스케줄링을 위해 간격 타이머도 사용할 수 있음

 

 

POSIX:XSI 타이머

  • struct itimerval 구조체를 사용함
    • struct timeval it_value; /* 다음 만료까지의 시간 /
    • struct timeval it_interval; / 타이머에 다시 로드할 값 */

 

 

 

#include <sys/time.h>
int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *restrict value, struct itimerval *restrict ovalue);

 

getitimer()

  • 타이머 'which'의 현재 값이 'value'에 저장됨

 

 

  • ITIMER_REAL
    • 실제 시간에서 감소하고 만료되면 SIGALRM 신호를 생성

 

  • ITIMER_VIRTUAL
    • 가상 시간(프로세스에서 사용하는 시간)에서 감소하고 만료되면 SIGVTALRM 신호를 생성

 

  • ITIMER_PROF
    • 가상 시간 및 프로세스의 시스템 시간에서 감소하고 만료되면 SIGPROF 신호를 생성

 

 

setitimer()

  • 'which'로 지정된 타이머를 'value'로 설정함
  • ovalue가 NULL이 아닌 경우 이전 값이 저장됨
  • value->it_interval이 0이 아닌 경우, 타이머는 만료될 때 이 값으로 다시 시작함
  • value->it_interval이 0이면 타이머는 만료될 때 다시 시작되지 않음
  • value->it_value가 0이면 실행 중인 경우 타이머가 중지됨

 

POSIX:TMR interval timers

 

소수의 클럭, 예를 들면 CLOCK_REALTIME과 같은 것들이 있으며, 프로세스는 각 클럭에 대해 많은 독립적인 타이머를 생성 가능

struct itimerspec 구조체를 기반으로 함

  • struct timespec it_interval; /* 타이머 주기 /
  • struct timespec it_value; / 만료 시간 */
  • struct timeval보다 더 높은 해상도를 가짐
#include <signal.h>
#include <time.h>
int timer_create(clockid_t clock_id, struct sigevent *restrict evp, timer_t *restrict timerid);
int timer_delete(timer_t timerid)

 

timer_create()

  • 프로세스별 타이머를 생성
  • fork에서 상속되지 않음
  • clock_id: 타이머가 기반으로 하는 클럭
  • timerid: 생성된 타이머의 ID를 보유
  • evp
    • 타이머 만료 시 발생할 비동기 알림을 지정함
    • NULL이면 타이머는 기본 신호를 생성함 (CLOCK_REALTIME에 대한 경우 SIGALRM)
    • evp->sigev_signo: 원하는 신호 번호
    • evp->sigev_notify: 타이머 만료 시 취해질 작업을 지정함
    • SIGEV_SIGNAL: 타이머 만료가 신호를 생성
    • SIGEV_NONE: 타이머가 신호를 생성하지 않도록 함

 

#include <time.h>
int timer_getoverrun(timer_t timerid);
int timer_gettime(timer_t timerid, struct itimerspec *value);
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
struct itimerspec *ovalue);

 

timer_settime()

  • 타이머를 시작하거나 중지
  • ‘flags'는 타이머가 상대 시간 또는 절대 시간을 사용하는지 여부를 지정함
  • ovalue'가 NULL이 아닌 경우 이전 값을 저장함

 

timer_overrun()

  • 타이머가 만료되는 동안 이전에 동일한 타이머의 만료에서 아직 처리되지 않은 신호가 대기 중인 경우, 생성된 신호 중 하나가 손실될 수 있음
  • 오버런의 횟수를 반환

 

Timer drift

  • 이유
    • 타이머가 만료되어야 할 때와 타이머가 재설정된 때 사이의 지연 시간
    • 2초 간격이 5 마이크로초의 지연으로 인해 사실은 2.000005초가 됨

 

예시

  • 타이머의 resolution이 10 ms인 경우, 주기가 22 ms인 반복 타이머가 있다고 친다면?
    • 오차는 각 만료마다 8 ms씩 증가함

절대 시간(absolute time)을 사용한 해결책

  • 타이머가 실제로 만료되어야 하는 시간을 추적하고, 매번 타이머를 설정할 때 이 값을 조정함
    • T = 현재 시간 + 22 ms 저장
    • 타이머를 22 ms 후에 만료되도록 설정
    • 신호 핸들러에서 타이머를 (T - 현재 시간 + 22ms) 후에 만료되도록 설정하고, T = T + 22 ms

 

POSIX:TMR 타이머를 사용한 해결책 (절대 시간)

  • timer_settime의 flags 매개변수를 TIMER_ABSOLUTE로 설정할 수 있음
    • *value 매개변수의 it_value 멤버에 지정된 시간은 시간 간격이 아닌 실제 시간을 나타냄
  • clock_gettime를 사용하여 현재 시간을 결정하고 22 ms를 더해줌 → 이를 T로 저장
  • 타이머를 TIMER_ABSOLUTE 플래그를 사용하여 T 시간에 만료되도록 설정
  • 타이머 신호 핸들러에서 T에 22 ms를 더하고 타이머를 T 시간에 만료되도록 설정
저작자표시 비영리 변경금지 (새창열림)

'Study > 시스템프로그래밍' 카테고리의 다른 글

[시스템프로그래밍] Mutex에 관하여  (4) 2023.12.05
[시스템프로그래밍] 스레드  (0) 2023.12.04
[시스템프로그래밍] Signals  (1) 2023.12.03
[시스템프로그래밍] pipe에 관하여  (1) 2023.11.02
[시스템프로그래밍] 디렉토리 엔트리, hard/symbolic link, stat에 관하여  (0) 2023.11.02
'Study/시스템프로그래밍' 카테고리의 다른 글
  • [시스템프로그래밍] Mutex에 관하여
  • [시스템프로그래밍] 스레드
  • [시스템프로그래밍] Signals
  • [시스템프로그래밍] pipe에 관하여
퀵차분
퀵차분
웹 프론트엔드 개발자를 꿈꾸고 있습니다 :)
  • 퀵차분
    QC's Devlog
    퀵차분
  • 전체
    오늘
    어제
    • 분류 전체보기 (165)
      • Frontend (28)
        • HTML, CSS (7)
        • Javascript (3)
        • React (11)
        • Typescript (2)
        • Next.js (4)
      • Node.js (3)
      • Study (40)
        • Modern JS Deep Dive (13)
        • SQL (1)
        • Network (1)
        • 프롬프트 엔지니어링 (4)
        • 인공지능 (9)
        • 시스템프로그래밍 (11)
        • 선형대수학 (1)
      • Intern (4)
      • KUIT (20)
      • Algorithm (48)
        • Baekjoon(C++) (26)
        • Programmers(JavaScript) (22)
      • 우아한테크코스(프리코스) (4)
      • Project (7)
        • PROlog (4)
        • Nomadcoder (2)
      • 생각 (4)
      • Event (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    음악추천
    리액트
    백준
    인공지능
    프로그래머스 자바스크립트
    티스토리챌린지
    프롬프트 엔지니어링
    typescript
    알고리즘
    자바스크립트
    프로그래머스
    next.js
    react
    오블완
    javascript
    KUIT
    타입스크립트
    시스템프로그래밍
    프론트엔드
    HTML
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
퀵차분
[시스템프로그래밍] 시간과 타이머
상단으로

티스토리툴바