Developer Log
  • Wiki
  • Books
    • 리눅스 시스템 프로그래밍
      • 핵심 개념 소개
        • 시스템 프로그래밍
        • API와 ABI
        • 리눅스 프로그래밍의 개념
          • 파일과 파일시스템
          • 프로세스
          • 사용자와 그룹
          • 권한
          • 시그널
          • 프로세스간 통신
          • 에러 처리
    • 데이터 베이스 첫걸음
      • 데이터베이스란
        • 데이터베이스의 역할을 생각해 보자
          • 우리와 데이터베이스의 관계
          • 데이터베이스의 기본 기능
          • 데이터베이스 종류
      • 관계형 데이터베이스란
        • 대표적인 DBMS를 알아보자
          • 관계형 데이터베이스란
          • SQL 기초 지식
          • 관계형 데이터베이스를 다루기 위한 사전 지식
      • 데이터베이스에 얽힌 돈 이야기
        • 초기비용과 운영비용을 생각하자
      • 데이터베이스와 아키텍처 구성
        • 다중화에 대해 생각해보자
          • 아키텍처란
          • 데이터베이스의 아키텍처
            • 역사와 개요
              • Stand-alone
              • 클라이언트/서버
              • Web 3계층
            • 가용성과 확장성의 확보
          • DB 서버의 다중화
            • 클러스터링
            • 리플리케이션
          • 성능을 추구하기 위한 다중화 - Shared Nothing
          • 적합한 아키텍처를 설계하기 위해
      • DBMS를 조작할 때 필요한 기본 지식
        • MySQL 설치해보자
        • MySQL과 커넥션 만들기, 데이터베이스에 전화걸기
        • SQL과 관리 명령의 차이
        • 관계형 데이터베이스의 계층
      • SQL 문의 기본
        • SELECT 문으로 테이블 내용을 살펴보자
        • SELECT 문을 응용해보자
        • 데이터를 갱신, 삽입, 제거해보자
        • 뷰를 작성하고 복수 테이블에서 선택해보자
      • 트랜잭션과 동시성 제어
      • 테이블 설계의 기초
      • 백업과 복구
      • 성능을 생각하자
    • 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴
      • 객체 지향
        • 들어가기
        • 객체 지향
        • 다형성과 추상 타입
        • 재사용: 상속보단 조립
      • 설계 원칙 / DI와 서비스 로케이터
        • 설계 원칙: SOLID
          • 단일 책임 원칙(Single Responsibility Principle)
          • 개방 폐쇄 원칙(Open - Closed Principle)
          • 리스코프 치환 원칙(Liskov Substitution Principle)
          • 인터페이스 분리 원칙(Interface Segregation Principle)
          • 의존 역전 원칙(Dependency Inversion Principle)
          • SOLID 정리
        • DI(Dependency Injection)와 서비스 로케이터
      • 주요 디자인 패턴
        • 디지인 패턴이란?
        • 전략(Strategy) 패턴
        • 템플릿 메서드(Template Method) 패턴
        • 상태(State) 패턴
        • 데코레이터(Decorator) 패턴
        • 프록시(Proxy) 패턴
        • 어댑터(Adapter) 패턴
        • 옵저버(Observer) 패턴
        • 미디에이터(Mediator) 패턴
        • 파사드(Facade) 패턴
        • 컴포지트(Composite) 패턴
        • 널(Null) 객체 패턴
        • 팩토리 메서드 패턴
        • 커맨드 패턴
        • 추상 팩토리 패턴
    • 테스트 주도 개발
      • 1부
        • 다중 통화를 지원하는 Money 객체
        • 타락한 객체
        • 모두를 위한 평등
        • 프라이버시
        • 솔직히 말하자면
        • 돌아온 '모두를 위한 평등'
        • 사과와 오렌지
Powered by GitBook
On this page

Was this helpful?

  1. Books
  2. 리눅스 시스템 프로그래밍
  3. 핵심 개념 소개
  4. 리눅스 프로그래밍의 개념

에러 처리

시스템 프로그래밍에서 에러는 함수 리턴 값으로 확인이 가능하며 특수한 변수인 errno로 에러가 발생한 구체적인 이유를 알 수 있다.

정확한 값은 함수에 따라 다르지만, 보통 에러가 발생하면 -1을 반환한다. 이 에러 값은 호출한 측에 에러가 발생했음을 알려주지만, 자세한 에러 이유는 알려주지 않는다. 이때 에러 원인을 찾아내기 위해 errno 변수를 사용한다.

<errno.h>
extern int errno;

이 값은 errno에 값을 대입한 함수를 호출한 직후에만 유효하다. 연이어 다른 함수를 실행하면 errno 값이 바뀌므로 주의해야 한다.

C 라이브러리는 errno 값을 그에 맞는 문자열 표현으로 변환하는 함수를 제공한다.

perror
#include <stdio.h>

void perror(const char *str);

perror 함수는 str이 가리키는 문자열 뒤에 콜론(:)을 붙인 다음에 errno가 기술하는 현재 에러를 문자열로 바꿔 표준 에러(stderr: stanard error)로 내보낸다.

if(close(fd) == -1) 
    perror ("close");

또한, C 라이브러리는 strerror()와 strerror_r() 함수를 제공한다.

strerror
#include <string.h>

char * strerror(int errnum);
strerror_r
#include <string.h>

int strerror_r(int errnum, char *buf, size_t len);

strerror() 함수는 errnum 에러에 대한 설명이 담긴 문자열에 대한 포인터를 반환한다. 문자열 내용을 애플리케이션에서 바꾸면 안 되지만, 연속해서 perror()와 strerror()를 호출하면 바뀔 수도 있다. 이런 의미에서 strerror()는 Thread Safe 하지 않다.

strerror_r() 함수는 스레드에서 사용할 수 있다. 이 함수는 buf가 가리키는 지점부터 len만큼 버퍼를 채운다. 성록하면 0을 반환하고 실패하면 -1 을 반환한다.

어떤 함수에서는 반환 타입의 전체 범위가 유효한 반환값인 경우도 있다. 이런 경우 호출 전에 errno를 0으로 초기화한 후에 함수를 호출하여 errno를 검사한다.

errno = 0;
arg = strtoul(buf, NULL, 0);
if(errno)
    perror("strtoul");

흔히 하는 실수로, 라이브러리나 시스템 콜에서 errno 값을 바꿀 수 있다는 사실을 잊은 채 errno 값을 검사하는 경우가 있다. 예를 들어 다음 코드는 버그가 있다.

if(fsync(fd) == -1) {
    fprintf(stderr, "fsync failed!\n");
    if(errno == EIO) 
        fprintf(stderr, "I/O error on %d!\n", fd);
}

만일 함수를 여러 번 호출하면서 errno 값을 보존해야 한다면 다른 곳에 따로 저장하자.

if(fsync(fd) == -1) {
    const int err = errno;
    fprintf(stderr, "fsync failed: %s\n", strerror(errno));
    if(err == EIO) {
        /* I/O와 관련된 에러라면 빠져나간다 */
        fprintf(stderr, "I/O error on %d!\n", fd);
        exit(EXIT_FAILURE);
    }
}

싱글 스레드 프로그램에서 errno는 전역 변수이지만, 멀티 스레드 프로그램에서 errno는 스레드 별로 저장되므로 스레드에서 사용이 가능하다.

Previous프로세스간 통신Next데이터 베이스 첫걸음

Last updated 6 years ago

Was this helpful?