컴퓨터/운영체제(주로 리눅스)

[리눅스] 오류 처리와 관련된 변수(errno)와 함수(strerror, perror) 활용

REAKWON 2022. 4. 14. 17:15

리눅스에 대한 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

오류 처리(Error Handling)

우리가 open으로 파일을 열때 -1의 값을 돌려받는다면 오류가 발생한 것입니다. 그런데 -1만 가지고는 우리는 왜 오류가 발생했는지 알 수가 없죠. 접근 권한 부족이라던가, 그런 파일이 존재하지 않는다던가 말입니다. open과 관련된 오류는 15가지 정도나 됩니다. 이런 원인을 알 수만 있다면 문제를 해결하는데 큰 도움이 되겠죠. 그래서 이번 포스팅에서는 오류의 원인을 어떻게 쉽게 알아 낼 수 있는지 관련된 내용입니다.

errno

errno는 일종의 오류의 코드가 담긴 변수입니다. 이 변수를 활용하기 위해서는 우리는 errno.h라는 헤더파일을 include시켜줘야합니다.

#include <errno.h>

 

errno.h 파일에는 errno와 errno에 설정될 수 있는 에러 코드가 담겨있습니다. 에러 코드는 상수로 담겨있으며 그 종류가 매우 많아서 여기에서는 담지 않겠습니다. 여러분들이 에러 코드에 대한 정보를 직접 확인해보시는 것을 추천해드리며 리눅스 매뉴얼 페이지에 존재합니다. 아래의 명령을 통해서 메뉴얼 페이지를 확인해보세요.

# man 3 errno

 

혹은 errno 명령을 사용하시면 됩니다. 위 명령은 moreutils라는 페키지에 존재하기 때문에 없으면 설치해줍니다. 

# apt install moreutils

 

errno -l 명령어 실행시 

# errno -l
EPERM 1 명령을 허용하지 않음
ENOENT 2 그런 파일이나 디렉터리가 없습니다
ESRCH 3 그런 프로세스가 없음
EINTR 4 중단된 시스템 콜
EIO 5 입력/출력 오류
ENXIO 6 그런 장치 혹은 주소가 없음
E2BIG 7 인수 명단이 너무 김
ENOEXEC 8 Exec 형식 오류

에러를 나타내는 상수는 모두 앞에 E가 붙는 점을 확인하세요.

 

strerror

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

errno 가지고는 어떤 오류인지 사람이 직접적으로 확인하기가 어렵습니다. 코드를 직접 확인하여서 에러 메시지를 출력해야합니다. 이런 번거로움없이 strerror에 인자로 errno를 전달하게 되면 알아서 오류 메시지를 반환해줍니다. 아래는 아주 간략한 예제입니다.

#include <errno.h>
#include <string.h>
#include <stdio.h>

int main(){
        char *msg;
        errno = EPERM;
        msg = strerror(errno);
        printf("error :%s\n",msg);

}

 

출력을 보게 되면 EPERM에 대한 오류 내용을 볼 수 있습니다. 

error :Operation not permitted

 

perror

#include <stdio.h>
void perror(const char *s);

perror는 strerror과 비슷하게 오류의 내용을 문자열로 출력하여 줍니다. 이때 전달되는 문자열 s는 우리가 출력해주길 원하는 문자열이며, 오류 내용은 errno에 따라서 알아서 출력을 해줍니다.

아래는 예제 코드입니다. 

#include <errno.h>
#include <stdio.h>

int main(){
        errno = EPERM;
        perror("error 발생");
}

출력을 보면 errno를 전달하지 않았음에도 함수 내부에서 errno를 확인하기 때문에 에러를 알 수 있습니다. 에러 내용은 위의 strerror의 메시지와 같은 것을 알 수 있죠? 내부적으로 strerror을 사용하는 것을 알 수 있습니다. 

error 발생: Operation not permitted

perror는 이렇게 errno를 직접 명시적으로 넣어주지 않아도 되기 때문에 매우 편리합니다.

 

open error 처리 코드

한 예로 open에 대한 error처리는 아래와 같이 수행이 됩니다. 오직 root만이 읽을 수 있는 파일이 있습니다. 

$ ls -l
-r-------- 1 root   root       0  4월 14 17:08 root_file

 

그리고 root 권한이 없는 일반 사용자로 아래의 코드를 짜서 실행해보면 열리지 않겠죠. 결국 open은 -1을 반환하게 됩니다. 그리고 왜 열지 못하는지는 perror를 통해 확인해볼 수 있습니다.

//err.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>

int main(){
        int fd = open("root_file", O_RDONLY);
        if(fd < 0){
                perror("file open error");
                exit(-1);
        }
        return 0;
}
$ gcc err.c
$ ./a.out
file open error: Permission denied

 

지금까지 오류를 쉽게 확인할 수 있는 내용이었습니다. 사실 error에 대해서 처리해주는 것이 여간 귀찮은 것이 아닌데 이러한 오류 처리 함수를 통해서 번거로움을 줄여보시기 바랍니다.

반응형