영어프랑스어스페인어

Ad


온웍스 파비콘

Explain_lca2010 - 클라우드에서 온라인

Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터를 통해 OnWorks 무료 호스팅 제공업체에서 Explain_lca2010 실행

이것은 Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터와 같은 여러 무료 온라인 워크스테이션 중 하나를 사용하여 OnWorks 무료 호스팅 제공업체에서 실행할 수 있는 Explain_lca2010 명령입니다.

프로그램:

이름


Explain_lca2010 - 매체를 찾을 수 없음: 읽기 시도를 중지해야 할 때 스트러러(3)의
마음.

자극


libexplain에 대한 아이디어는 1980년대 초에 떠올랐습니다. 시스템 호출이 있을 때마다
오류를 반환하면 커널은 무엇이 잘못되었는지 정확히 알고... 이를 다음으로 압축합니다.
8비트 미만 에르 노. 사용자 공간은 커널과 동일한 데이터에 액세스할 수 있습니다.
사용자 공간이 오류를 유발한 정확한 원인을 파악할 수 있어야 합니다.
반환하고 이것을 사용하여 좋은 오류 메시지를 작성합니다.

그것이 그렇게 간단할 수 있습니까?

오류 메시지 as 피네스
좋은 오류 메시지는 종종 일정이 잡히면 삭제되는 "XNUMX%" 작업입니다.
압박감이 프로젝트를 압박합니다. 그러나 좋은 오류 메시지는
사용자가 겁에 질려 방황할 때 사용자 경험에 대한 불균형적인 개선
평소 접하지 못한 미지의 영역. 이것은 쉬운 일이 아닙니다.

애벌레 프로그래머로서 작성자는 (완전히 정확한) 오류 문제를 보지 못했습니다.
다음과 같은 메시지:
부동 예외(코어 덤프)
프로그래머가 아닌 대안의 해석이 지적될 때까지. 하지만 그건 아니야
Unix 오류 메시지에만 문제가 있습니다. 다음과 같은 오류 메시지가 얼마나 자주 표시됩니까?
$ ./멍청한
파일을 열 수 없습니다
$
이 시점에서 개발자를 위한 두 가지 옵션이 있습니다.

1.
다음과 같은 디버거를 실행할 수 있습니다. gdb(1) 또는

2.
당신이 사용할 수있는 추적하다(1) 또는 지붕틀(1) 안을 들여다보다.

· 사용자는 이러한 도구에 대한 액세스 권한이 없을 수도 있음을 기억하십시오.
그들을 사용합니다. (정말 오랜만이다. 유닉스 초보자 "만 썼다.
장치 드라이버".)

그러나 이 예에서는 다음을 사용하여 추적하다(1) 밝히다
$ 추적하다 -e 추적=열기 ./멍청한
open("some/file", O_RDONLY) = -1 ENOENT(해당 파일이나 디렉토리가 없음)
파일을 열 수 없습니다
$
이것은 오류 메시지가 제공하는 것보다 훨씬 더 많은 정보입니다. 일반적으로
어리석은 소스 코드는 다음과 같습니다
int fd = open("무엇", O_RDONLY);
만약 (fd < 0)
{
fprintf(stderr, "파일을 열 수 없습니다\n");
출구(1);
}
사용자에게 알리지 않음 어느 파일을 만들고 사용자에게 알리지 않습니다. 어느 오류. 파일이었나요
거기에도? 권한 문제가 있었나요? 열려고 했음을 알려줍니다.
파일이지만 아마도 우연이었을 것입니다.

실마리 스틱을 잡고 애벌레 프로그래머를 물리치십시오. 그에 대해 말해 오류(3).
다음에 프로그램을 사용할 때 다른 오류 메시지가 표시됩니다.
$ ./멍청한
열기: 해당 파일이나 디렉토리가 없습니다.
$
진전이 있었지만 우리가 기대했던 것은 아닙니다. 오류 메시지가 표시되면 사용자는 어떻게 문제를 해결할 수 있습니까?
문제가 무엇인지 그에게 말하지 않습니까? 소스를 보면 알겠지만
int fd = open("무엇", O_RDONLY);
만약 (fd < 0)
{
오류("열기");
출구(1);
}
실마리 스틱으로 다시 실행할 시간입니다. 이번에는 오류 메시지가 한 단계
앞으로 한 걸음 뒤로:
$ ./멍청한
무엇: 해당 파일 또는 디렉토리 없음
$
이제 우리는 열려고 했던 파일을 알고 있지만 더 이상 파일이 열려 있다는 정보를 받지 못했습니다. 열 수(2)
실패했습니다. 이 경우에는 중요하지 않을 수 있지만 다음에는 중요할 수 있습니다.
다른 시스템 호출. 그럴 수 있었다 creat(2) 대신 다음을 암시하는 작업
다른 권한이 필요합니다.
const char *파일명 = "무엇";
int fd = open(파일명, O_RDONLY);
만약 (fd < 0)
{
오류(파일명);
출구(1);
}
위의 예제 코드는 불행히도 non-larval 프로그래머에게도 일반적입니다. 시간
우리의 padawan 학습자에게 스트러러(3) 시스템 호출.
$ ./멍청한
열 수 무엇: 해당 파일 또는 디렉토리 없음
$
이것은 사용자에게 제공될 수 있는 정보를 최대화합니다. 코드는 다음과 같습니다.
이:
const char *파일명 = "무엇";
int fd = open(파일명, O_RDONLY);
만약 (fd < 0)
{
fprintf(stderr, "%s 열기: %s\n", 파일명, strerror(errno));
출구(1);
}
이제 시스템 호출, 파일 이름 및 오류 문자열이 있습니다. 여기에는 모든
정보 추적하다(1) 인쇄. 그것은 얻을 수 있습니다.

아니면 그렇지?

제한 사항 of 오류 스트러러
저자가 1980년대에 본 문제는 오류 메시지가 불완전하다는 것이었습니다.
"해당 파일이나 디렉토리가 없음"은 "일부" 디렉토리 또는 "맡은 일" 파일에
"일부" 디렉토리?

에 대한 매뉴얼 페이지를 간단히 살펴보십시오. 스트러러(3)은 다음과 같이 말하고 있습니다.
strerror - 오류 번호를 설명하는 반환 문자열
참고: 오류를 설명하고 있습니다. 번호, 오류가 아닙니다.

한편, 커널 알고있다 오류가 무엇인지. 에 특정한 포인트가 있었다.
커널 코드가 분기되어 "아니오"라고 말한 특정 조건으로 인해 발생하는 커널 코드.
사용자 공간 프로그램이 특정 조건을 파악하고 더 나은 오류를 작성할 수 있습니까?
메시지?

그러나 문제는 더 깊어집니다. 도중에 문제가 발생하면 어떻게 합니까? 읽기(2) 시스템
전화보다는 열 수(2) 전화? 다음과 관련된 오류 메시지는 간단합니다.
열 수(2) 파일 이름을 포함하려면 바로 거기에 있습니다. 그러나 파일 이름을 포함할 수 있도록
와 관련된 오류에서 읽기(2) 시스템 호출, 파일 이름을 모두 전달해야 합니다.
파일 디스크립터뿐만 아니라 호출 스택을 다운시키는 방법.

그리고 여기에 그레이트 비트가 있습니다. 커널은 이미 파일 이름을 알고 있습니다.
설명자가 와 연결됩니다. 프로그래머가 중복 데이터를 모두 전달해야 하는 이유
결코 발행되지 않을 수 있는 오류 메시지를 개선하기 위해 호출 스택을 아래로 내려가는 방법은 무엇입니까? 에
실제로 많은 프로그래머는 신경 쓰지 않으며 결과 오류 메시지는
그것.

그러나 그것은 제한된 리소스와 공유 라이브러리가 없는 PDP1980의 11년대였습니다. 뒤
그런 다음 Unix의 풍미가 포함되지 않았습니다. / proc 기초적인 형태로도 이소프(1) 프로그램
십 년이 넘었습니다. 그래서 그 아이디어는 비현실적인 것으로 보류되었습니다.

레벨 무한대 고객 지원
레벨 무한 지원을 상상해보십시오. 당신의 직업 설명은 당신이 결코
사용자와 대화해야 합니다. 그렇다면 왜 여전히 원하는 사람들의 끊임없는 흐름이 있습니까?
지역 Unix 전문가인 당신이 또 다른 오류 메시지를 해독하기 위해?

이상하게도 25년 후, 단순한 허가 시스템에도 불구하고 완전한
일관성, 대부분의 Unix 사용자는 여전히 "해당 파일 또는 디렉터리 없음"을 디코딩하는 방법을 모릅니다.
또는 그들이 매일 보는 다른 수수께끼 같은 오류 메시지. 또는 적어도
그들.

XNUMX단계 기술 지원에서 오류 메시지를 해독할 필요가 없다면 좋지 않을까요?
사용자가 전화를 걸지 않고도 이해할 수 있는 오류 메시지가 있으면 좋지 않을까요?
기술 지원?

요즈음 / proc Linux에서는 디코딩에 필요한 정보를 제공할 수 있습니다.
대부분의 오류 메시지를 표시하고 사용자에게 오류 메시지의 가장 가까운 원인을 알려줍니다.
문제. 제한된 시스템에서 / proc 구현, 이소프(1) 명령은 다음을 채울 수 있습니다.
많은 공백.

2008년에는 번역 요청이 작가에게 너무 자주 발생했습니다. 그것은
그 25년 된 아이디어를 다시 검토할 시간이고 libexplain이 그 결과입니다.

사용 L' 도서관


라이브러리에 대한 인터페이스는 가능한 경우 일관성을 유지하려고 합니다. 시작하자
사용 예 스트러러(3) :
if (이름 바꾸기(old_path, new_path) < 0)
{
fprintf(stderr, "이름 %s %s: %s\n", old_path, new_path,
strerror(errno));
출구(1);
}
libexplain 뒤에 있는 아이디어는 다음을 제공하는 것입니다. 스트러러(3) 동등한 마다 시스템 호출,
더 자세한 오류를 제공할 수 있도록 해당 시스템 호출에 맞게 특별히 조정되었습니다.
섹션의 "오류" 제목 아래에 표시되는 많은 정보가 포함된 메시지
2 및 3 사람 실제 상황, 실제 주장에 대한 정보가 추가된 페이지
값 및 시스템 제한.

XNUMXD덴탈의 단순, 간단, 편리 케이스
XNUMXD덴탈의 스트러러(3) 교체:
if (이름 바꾸기(old_path, new_path) < 0)
{
fprintf(stderr, "%s\n", Explain_rename(old_path, new_path));
출구(1);
}

XNUMXD덴탈의 에르노 케이스
명시적으로 전달할 수도 있습니다. 에르 노(3) 값, 먼저 어떤 작업을 수행해야 하는 경우
방해가 되는 처리 에르 노, 오류 복구와 같은:
if (이름 바꾸기(old_path, new_path < 0))
{
int old_errno = errno;
...암호 방해하다 에르 노...
fprintf(stderr, "%s\n", Explain_errno_rename(old_errno,
이전_경로, 새_경로));
출구(1);
}

XNUMXD덴탈의 다중 스레드 케이스
일부 응용 프로그램은 다중 스레드이므로 libexplain의 내부 파일을 공유할 수 없습니다.
완충기. 다음을 사용하여 자체 버퍼를 제공할 수 있습니다.
if (연결 해제(경로 이름))
{
문자 메시지[3000];
Explain_message_unlink(메시지, 크기(메시지), 경로명);
오류_대화상자(메세지);
반환 -1;
}
그리고 완전성을 위해 둘 다 에르 노(3) 및 스레드 안전:
ssize_t nbytes = 읽기(fd, 데이터, sizeof(데이터));
if (nbytes < 0)
{
문자 메시지[3000];
int old_errno = errno;
...오류 회복...
Explain_message_errno_read(메시지, 크기(메세지),
old_errno, fd, 데이터, sizeof(data));
오류_대화상자(메세지);
반환 -1;
}

이들은 대체 strerror_r(3), 시스템이 있는 경우.

인터페이스 설탕
프로그래머가 사용할 수 있도록 편의 기능으로 추가 된 기능 세트
libexplain 라이브러리에서 저자가 가장 일반적으로 사용하는 libexplain 함수로 밝혀졌습니다.
명령줄 프로그램:
int fd = Explain_creat_or_die(파일 이름, 0666);
이 함수는 새 파일을 생성하려고 시도합니다. 할 수 없으면 오류 메시지를 인쇄하고
EXIT_FAILURE로 종료합니다. 오류가 없으면 새 파일 설명자를 반환합니다.

관련 기능:
int fd = Explain_creat_on_error(파일 이름, 0666);
실패 시 오류 메시지를 인쇄하지만 원래 오류 결과도 반환합니다.
에르 노(3) 역시 성가시다.

All 전에, other 체계 통화
일반적으로 모든 시스템 호출에는 고유한 포함 파일이 있습니다.
#포함하다name.h>
XNUMX개의 함수에 대한 함수 프로토타입을 정의합니다.

· 설명_name,

· 설명_errno_name,

· 설명_메시지_name,

· Explain_message_errno_name,

· 설명_name_또는_죽고

· 설명_name_에러.

모든 함수 프로토타입에는 Doxygen 문서가 있으며 이 문서는 is 지원 제거
포함 파일이 설치된 경우.

XNUMXD덴탈의 기다리다(2) 시스템 호출(및 친구)에는 실패를 해석하는 몇 가지 추가 변형이 있습니다.
EXIT_SUCCESS가 아닌 종료 상태가 됩니다. 이것은 적용됩니다 체계(3)과하면 닫기(3) as
잘.

적용 범위에는 221개의 시스템 호출과 547개의 ioctl 요청이 포함됩니다. 더 많은 시스템이 있습니다
아직 구현하지 않은 호출. 다음과 같이 절대 반환되지 않는 시스템 호출 출구(2), 존재하지 않음
도서관에 있고 앞으로도 없을 것입니다. 그만큼 임원 시스템 호출 제품군 are 지원하기 때문에
오류가 있을 때 반환됩니다.

고양이
이것은 가상의 "cat" 프로그램이 완전한 오류 보고와 함께 보일 수 있는 것입니다.
libexplain을 사용합니다.
#포함하다
#포함
#포함하다
libexplain에 대한 포함과 일반적인 용의자가 있습니다. (절약을 원하시면
전처리기 로드, 특정name.h>는 포함합니다.)
정적 공극
프로세스(파일 *fp)
{
을위한 (;;)
{
문자 버퍼[4096];
size_t n = Explain_fread_or_die(버퍼, 1, sizeof(버퍼), fp);
만약 (!n)
하다;
Explain_fwrite_or_die(버퍼, 1, n, 표준 출력);
}
}
XNUMXD덴탈의 방법 함수는 파일 스트림을 표준 출력으로 복사합니다. 오류가 발생하면
읽기 또는 쓰기에 대해 보고됩니다(경로 이름은
오류) 명령이 EXIT_FAILURE와 함께 종료됩니다. 우리는 추적에 대해 걱정하지 않습니다
경로 이름을 사용하거나 호출 스택 아래로 전달합니다.
INT
메인(int argc, char **argv)
{
을위한 (;;)
{
int c = getopt(argc, argv, "o:");
만약 (c == EOF)
하다;
스위치 (c)
{
케이스 'o':
Explain_freopen_or_die(optarg, "w", 표준 출력);
하다;
이 코드의 재미있는 부분은 libexplain이 오류를 보고할 수 있다는 것입니다. ...을 포함하여 전에, 경로명 조차
만약에 당신이 하지 여기에서 수행한 것처럼 stdout을 명시적으로 다시 엽니다. 우리는 걱정조차 하지 않는다
파일 이름을 추적합니다.
기본값 :
fprintf(stderr, "사용법: %ss [ -o ] ...\N",
인수[0]);
반환 EXIT_FAILURE;
}
}
if (옵션 == 인수)
프로세스(표준 입력);
그렇지 않으면
{
동안 (optind < argc)
{
파일 *fp = Explain_fopen_or_die(argv[optind]++, "r");
프로세스(fp);
설명_fclose_or_die(fp);
}
}
표준 출력은 암시적으로 닫히지만 오류 보고서가 표시되기에는 너무 늦습니다.
버퍼링된 I/O가 아직 아무 것도 작성하지 않은 경우를 대비하여 여기에서 수행합니다.
ENOSPC 오류 등이 있습니다.
Explain_fflush_or_die(stdout);
반환 EXIT_SUCCESS;
}
그게 다야. 전체 오류 보고, 명확한 코드.

러스티의 규모 of 인터페이스 친절
익숙하지 않은 분들을 위해 Rusty Russel의 "How Do I Make this Hard to misuse?"
페이지는 API 디자이너가 반드시 읽어야 하는 페이지입니다.
http://ozlabs.org/~rusty/index.cgi/tech/2008‐03‐30.html

10. 그건 불가능한 얻을 잘못된.

목표는 높게 설정해야 하고, 야심차게 높게 설정해야 목표를 달성할 수 있다고 생각하지 않습니다.
당신이 없을 때 끝납니다.

libexplain 라이브러리는 가짜 포인터와 다른 많은 가짜 시스템 호출 매개변수를 감지합니다.
그리고 일반적으로 가장 힘든 상황에서도 segfaults를 피하려고 합니다.

libexplain 라이브러리는 스레드로부터 안전하도록 설계되었습니다. 더 많은 실제 사용 가능성
개선할 수 있는 부분을 공개합니다.

가장 큰 문제는 실제 함수 이름 자체에 있습니다. C가 없기 때문에
이름 공간에서 libexplain 라이브러리는 항상 explain_ name 접두사를 사용합니다. 이것이
기호 충돌을 피하기 위해 의사 이름 공간을 만드는 전통적인 방법입니다.
그러나 부자연스럽게 들리는 이름이 있습니다.

9. XNUMXD덴탈의 컴파일러 or 링크 하지 않습니다 하자 당신 얻을 it 잘못된.

일반적인 실수는 Explain_open_or_die가 의도된 위치에 Explain_open을 사용하는 것입니다.
다행히 컴파일러는 이 시점에서 종종 유형 오류를 발생시킵니다( 할당할 수 없습니다
const char * rvalue를 int lvalue로).

8. XNUMXD덴탈의 컴파일러 의지 경고 if 당신 얻을 it 잘못된.

Explain_rename_or_die가 의도되었을 때 Explain_rename이 사용되면 다른 문제가 발생할 수 있습니다.
문제. GCC에는 유용한 warn_unused_result 함수 속성이 있으며 libexplain은
라이브러리는 모든 Explain_에 첨부합니다.name 경고를 생성하는 함수 호출
이런 실수를 하십시오. 이것을 결합 GCC -워러 이것을 레벨 9로 승격시키십시오.

7. XNUMXD덴탈의 분명한 사용 is (아마) 전에, 수정 하나.

함수 이름은 의미를 전달하기 위해 선택되었지만 항상 그런 것은 아닙니다.
성공적인. 설명하면서_name_또는_죽고 설명_name_on_error는 상당히 설명적이며,
덜 사용되는 스레드 안전 변형은 디코딩하기가 더 어렵습니다. 함수 프로토타입은
컴파일러를 이해하는 방향으로 가고 헤더 파일의 Doxygen 주석은 사용자에게 도움이 됩니다.
이해를 향해.

6. XNUMXD덴탈의 name 말하다 당신 방법 사용 그것.

Explain_을 읽는 것이 특히 중요합니다.name_or_die는 "설명(name 아니면 죽는다)”.
일관된 Explain_ 이름 공간 접두사를 사용하면 몇 가지 불행한 부작용이 있습니다.
명확성 부서도 마찬가지입니다.

이름의 단어 순서도 인수의 순서를 나타냅니다. 논쟁 거리
항상 목록 end 시스템 호출에 전달된 것과 동일한 인수를 사용합니다. 모든 of 그들. 면
_errno_는 이름에 나타나며 해당 인수는 항상 시스템 호출 인수보다 우선합니다. 만약에
_message_가 이름에 나타나며 두 개의 인수가 항상 먼저 옵니다.

5. Do it 연락해주세요 or it 의지 하다 at 실행 시간.

libexplain 라이브러리는 가짜 포인터와 다른 많은 가짜 시스템 호출 매개변수를 감지합니다.
그리고 일반적으로 가장 힘든 상황에서도 segfaults를 피하려고 합니다. 그것은해야
런타임에 중단되지는 않지만 실제로 더 많이 사용하면 의심할 여지 없이 개선될 것입니다.

일부 오류 메시지는 최종 사용자가 아닌 개발자와 유지 관리자를 대상으로 합니다.
버그 해결을 도울 수 있습니다. "런타임에 휴식"이 아니라 "정보 제공"
런타임”(시스템 호출 barfs 이후).

4. 팔로우 공통의 컨벤션 너는 얻을 it 권리.

C에는 네임스페이스가 없기 때문에 libexplain 라이브러리는 항상 Explain_ name을 사용합니다.
접두사. 이것은 다음을 피하기 위해 의사 이름 공간을 만드는 전통적인 방법입니다.
기호 충돌.

모든 libexplain 호출의 후행 인수는 시스템 호출과 동일합니다.
설명하고 있습니다. 이것은 다음과 같은 일관된 규칙을 제공하기 위한 것입니다
시스템이 스스로를 호출합니다.

3. 읽기 전에, 선적 서류 비치 너는 얻을 it 권리.

libexplain 라이브러리는 각각에 대한 완전한 Doxygen 문서를 갖는 것을 목표로 합니다.
공개 API 호출(그리고 내부적으로도).

메세지 내용


libexplain에서 작업하는 것은 자동차가 켜져 있을 때 자동차의 밑면을 보는 것과 같습니다.
정비공의 호이스트. 그 아래에는 추악한 것들이 있고 진흙과 찌꺼기가 있습니다.
사용자는 거의 그것을 볼 수 없습니다. 좋은 오류 메시지는 다음과 같은 사용자에게도 정보를 제공해야 합니다.
밑면을 자주 볼 필요가 없을 정도로 운이 좋았고,
전화로 사용자의 설명을 듣는 정비사에게 유익한 정보입니다. 이것은
쉬운 작업이 없습니다.

첫 번째 예를 다시 살펴보면 libexplain을 사용하는 코드는 다음과 같습니다.
int fd = Explain_open_or_die("일부/사물", O_RDONLY, 0);
다음과 같은 오류 메시지와 함께 실패합니다
open(경로 이름 = "일부/파일", 플래그 = O_RDONLY) 실패, 해당 파일 또는 디렉터리가 없습니다.
(2, ENOENT) 현재 디렉토리에 "some" 디렉토리가 없기 때문에
이렇게 세 조각으로 나뉩니다
시스템 호출 실패한, 시스템 오류 때문에
설명

때문에
"왜냐하면" 앞의 메시지 부분이 비-에 대해 지나치게 기술적인 것으로 볼 수 있습니다.
기술 사용자, 주로 시스템 호출 자체를 정확하게 인쇄한 결과
오류 메시지의 시작 부분. 그리고 그것은 다음과 같이 보입니다. 추적하다(1) 출력, 보너스 괴짜용
포인트.
open(경로 이름 = "일부/파일", 플래그 = O_RDONLY) 실패, 해당 파일 또는 디렉터리가 없습니다.
(2, 에노엔트)
오류 메시지의 이 부분은 개발자가 코드를 작성할 때 필수적이며,
버그 보고서를 읽고 버그를 수정해야 하는 관리자에게도 똑같이 중요합니다.
암호. 무엇이 실패했는지 정확히 알려줍니다.

이 텍스트가 사용자에게 표시되지 않으면 사용자는 복사하여 붙여넣을 수 없습니다.
버그 보고서 및 버그 보고서에 없으면 유지 관리자는 실제로 무엇이 되었는지 알 수 없습니다.
잘못된.

기술 직원이 자주 사용하는 추적하다(1) 또는 지붕틀(1) 이 정확한 정보를 얻으려면
버그 보고서를 읽을 때 이 길은 열려 있지 않습니다. 버그 리포터 시스템은 멀다
떨어져 있고, 지금쯤이면 훨씬 다른 상태에 있습니다. 따라서 이 정보는
버그 보고서, 즉 오류 메시지에 있어야 함을 의미합니다.

시스템 호출 표현은 메시지의 나머지 부분에도 컨텍스트를 제공합니다. 필요한 경우
문제가 되는 시스템 호출 인수가 발생하면 설명에서 이름으로 참조할 수 있습니다.
"때문에" 뒤에. 또한 모든 문자열은 완전히 인용되고 이스케이프된 C 문자열이므로
포함된 줄 바꿈 및 인쇄되지 않는 문자로 인해 사용자 터미널이 실행되지 않습니다.
얽힌.

XNUMXD덴탈의 시스템 오류 에서 나오는 것입니다 스트러러(2) 오류 기호를 더한 것입니다. 참을성이 없고
전문 시스템 관리자는 이 시점에서 읽기를 중단할 수 있지만 현재까지 작성자의 경험은 다음과 같습니다.
더 읽어보면 보람이 있습니다. (보상이 없다면 아마도
libexplain을 개선할 수 있습니다. 물론 코드 기여도 환영합니다.)

때문에
이는 비기술적 사용자를 대상으로 하는 오류 메시지의 일부입니다. 너머 보인다
간단한 시스템 호출 인수를 찾고 더 구체적인 것을 찾습니다.
현재 디렉토리에 "일부" 디렉토리가 없습니다.
이 부분은 오류의 근위 원인을 일반 언어로 설명하려고 시도합니다.
여기에서 국제화가 필수적입니다.

일반적으로 정책은 가능한 한 많은 정보를 포함하여 사용자가
그것을 찾을 필요가 없습니다 (그리고 버그 보고서에서 그것을 떠나지 않습니다).

국제화
libexplain 라이브러리에 있는 대부분의 오류 메시지는 국제화되었습니다. 거기
아직 현지화되지 않았으므로 모국어로 설명을 원하시면
기여해주세요.

위의 "대부분의" 한정자는 개념 증명이
구현에는 국제화 지원이 포함되지 않았습니다. 코드 베이스는
일반적으로 메시지를 리팩토링하여 각 오류가
메시지 문자열은 코드에 정확히 한 번 나타납니다.

의 부분을 조합해야 하는 언어에 대한 규정이 만들어졌습니다.
시스템 호출 실패한, 시스템 오류 때문에 설명
지역화된 오류 메시지에서 올바른 문법을 위해 다른 순서로.

검시
프로그램이 아직 libexplain을 사용하지 않아 사용할 수 없는 경우가 있습니다. 추적하다(1)
어느 하나. 있다 설명(1) libexplain에 포함된 명령으로 다음 작업에 사용할 수 있습니다.
기본 시스템의 상태가 너무 많이 변경되지 않은 경우 오류 메시지를 해독합니다.
$ 설명 이름 변경 /tmp/bar/baz -e 에노엔트
이름 바꾸기(oldpath = "foo", newpath = "/tmp/bar/baz") 실패, 해당 파일 또는 디렉터리가 없습니다.
(2, ENOENT) newpath "에 "bar" 디렉토리가 없기 때문에 "/ TMP" 디렉토리
$
시스템 호출 인수 이름을 사용하여 경로 모호성을 해결하는 방법에 유의하십시오. 의
물론 오류와 시스템 호출을 알아야 합니다. 설명(1) 유용하다. 로
제쳐두고, 이것은 libexplain 자동 테스트 스위트에서 다음을 확인하는 데 사용하는 방법 중 하나입니다.
libexplain이 작동합니다.

철학
"내가 찾을 줄도 몰랐던 것들을 포함하여 모든 것을 말해줘."

라이브러리는 정적으로 링크될 때 사용자가 지정한 코드만
실제로 사용이 연결됩니다. 이것은 소스 파일당 하나의 기능을 가짐으로써 달성됩니다.
가능할 때마다.

더 많은 정보를 제공할 수 있게 되면 libexplain이 그렇게 할 것입니다. 사용자가 적을수록
스스로 추적해야 할 수록 좋습니다. 이것은 UID가
사용자 이름, GID는 그룹 이름과 함께, PID는 프로세스와 함께 제공됩니다.
이름, 파일 설명자 및 스트림에는 경로 이름이 수반됩니다. .

경로를 확인할 때 경로 구성 요소가 없으면 libexplain은 유사한 경로를 찾습니다.
인쇄상의 오류에 대한 대안을 제안하기 위해 이름.

libexplain 라이브러리는 가능한 한 적은 힙을 사용하려고 시도하며 일반적으로 사용하지 않습니다. 이것은
때로는 프로세스 상태를 교란시키지 않도록 가능한 한
피하기 어려운.

libexplain 라이브러리는 전역 변수를 피함으로써 스레드로부터 안전하도록 시도합니다.
스택에 가능한 한 많이 상태를 유지합니다. 하나의 공통 메시지 버퍼가 있으며,
그것을 사용하는 함수는 스레드로부터 안전하지 않은 것으로 문서화되어 있습니다.

libexplain 라이브러리는 프로세스의 신호 처리기를 방해하지 않습니다. 이것은 만든다
포인터가 챌린지를 세그폴트할지 여부를 결정하지만 불가능한 것은 아닙니다.

정보가 시스템 호출을 통해 이용 가능하고 정보를 통해 이용 가능한 경우 / proc
항목, 시스템 호출이 선호됩니다. 이것은 프로세스의 상태를 방해하는 것을 피하기 위한 것입니다.
파일 디스크립터를 사용할 수 없는 경우도 있습니다.

libexplain 라이브러리는 대용량 파일 지원으로 컴파일됩니다. 대/소가 없다
정신 분열증. 이것이 API의 인수 유형에 영향을 미치고 오류가 발생하는 경우
필요한 대용량 파일 정의가 없는 경우.

FIXME: 파일 시스템 할당량이 코드에서 처리되는지 확인하는 작업이 필요합니다. 이것
일부에 적용 getrlimit(2) 경계도 마찬가지입니다.

상대 경로가 정보가 없는 경우가 있습니다. 예: 시스템 데몬,
서버 및 백그라운드 프로세스. 이러한 경우 오류에 절대 경로가 사용됩니다.
설명.

PATH 분해능


짧은 버전: 참조 경로_해상도(7).

긴 버전: 대부분의 사용자는 들어본 적이 없습니다. 경로_해상도(7) 및 많은 고급 사용자
읽어본 적이 없습니다. 다음은 주석이 달린 버전입니다.

단계 1: 스타트 of 전에, 분해능 방법
경로 이름이 슬래시("/") 문자로 시작하는 경우 시작 조회 디렉토리는
호출 프로세스의 루트 디렉토리.

경로 이름이 슬래시("/") 문자로 시작하지 않으면 시작 조회
해결 프로세스의 디렉토리는 프로세스의 현재 작업 디렉토리입니다.

단계 2: 걷다 따라 전에, 통로
현재 조회 디렉토리를 시작 조회 디렉토리로 설정합니다. 이제 각 비
경로 이름의 마지막 구성 요소, 여기서 구성 요소는 슬래시("/")로 구분된 하위 문자열입니다.
문자, 이 구성 요소는 현재 조회 디렉토리에서 조회됩니다.

프로세스에 현재 조회 디렉토리에 대한 검색 권한이 없으면 EACCES
오류가 반환됩니다("권한 거부됨").
open(경로 이름 = "/home/archives/.ssh/private_key", 플래그 = O_RDONLY) 실패,
프로세스에 검색 권한이 없기 때문에 권한이 거부되었습니다(13, EACCES).
경로 이름 "/home/archives/.ssh" 디렉토리에 대한 프로세스 유효 GID 1000
"pmiller"는 디렉토리 소유자 1001 "archives"와 일치하지 않으므로 소유자는
권한 모드 "rwx"는 무시되고 다른 권한 모드는 "---"이며
프로세스에 권한이 없음(DAC_READ_SEARCH 기능이 없음)

구성 요소를 찾을 수 없으면 ENOENT 오류가 반환됩니다("해당 파일 또는 디렉터리 없음").
unlink(pathname = "/home/microsoft/rubbish") 실패, 해당 파일 또는 디렉터리가 없습니다(2,
ENOENT) 경로 이름에 "microsoft" 디렉토리가 없기 때문에 "홈 /" 디렉토리

또한 사용자가 경로 이름을 잘못 입력할 때 몇 가지 지원이 있습니다.
ENOENT가 반환됩니다.
open(pathname = "/user/include/fcntl.h", flags = O_RDONLY) 실패, 해당 파일이 없거나
경로명 "/"에 "user" 디렉토리가 없기 때문에 디렉토리(2, ENOENT)
디렉토리, 대신 "usr" 디렉토리를 의미합니까?

구성 요소가 발견되었지만 디렉토리나 심볼릭 링크가 아닌 경우 ENOTDIR
오류가 반환됩니다("디렉토리 아님").
open(경로 이름 = "/home/pmiller/.netrc/lca", 플래그 = O_RDONLY) 실패, 아니요
경로 이름에 ".netrc" 일반 파일이 있기 때문에 디렉토리(20, ENOTDIR)
"/home/pmiller" 디렉토리가 아닌 경우 디렉토리로 사용 중입니다.

구성 요소가 발견되고 디렉터리인 경우 현재 조회 디렉터리를 해당 디렉터리로 설정합니다.
디렉토리로 이동하고 다음 구성 요소로 이동합니다.

구성 요소가 발견되고 심볼릭 링크(symlink)인 경우 먼저 이 심볼릭 링크를 해결합니다.
링크(현재 조회 디렉토리를 조회 디렉토리 시작으로 사용). 오류가 발생하면
오류가 반환됩니다. 결과가 디렉터리가 아니면 ENOTDIR 오류가 반환됩니다.
unlink(경로 이름 = "/tmp/dangling/rubbish") 실패, 해당 파일 또는 디렉터리가 없습니다(2,
ENOENT) 경로 이름에 "매달린" 심볼릭 링크가 있기 때문에 "/ TMP" 디렉토리
존재하지 않는 "아무데도"를 나타냅니다.
심볼릭 링크의 해결이 성공하고 디렉토리를 반환하면 현재
디렉토리를 찾아 해당 디렉토리로 이동하고 다음 구성 요소로 이동합니다. 참고로
여기서 해결 프로세스에는 재귀가 포함됩니다. 스택으로부터 커널을 보호하기 위해
오버플로 및 서비스 거부로부터 보호하기 위해 최대 제한이 있습니다.
재귀 깊이 및 따라오는 최대 심볼릭 링크 수. ELOOP 오류는
최대값을 초과하면 반환됩니다("심볼릭 링크 수준이 너무 많음").
open(pathname = "/tmp/dangling", flags = O_RDONLY) 실패, 레벨이 너무 많습니다.
에서 심볼릭 링크 루프가 발생했기 때문에 심볼릭 링크(40, ELOOP)
"/tmp/dangling"에서 시작하는 경로 이름
심볼릭 링크가 너무 많으면 ELOOP 또는 EMLINK 오류가 발생할 수도 있습니다.
루프가 감지되었습니다.
open(pathname = "/tmp/rabbit-hole", flags = O_RDONLY) 실패, 너무 많은 수준
심볼릭 링크(40, ELOOP)에서 너무 많은 심볼릭 링크가 발생했기 때문에
경로명 (8)
실제 제한도 어떻게 인쇄되는지 확인하십시오.

단계 3: Find 전에, 최후의 항목
경로명의 최종 구성요소 조회는 다른 모든 구성요소의 조회와 동일합니다.
구성 요소는 이전 단계에서 설명한 대로 두 가지 차이점이 있습니다.

(i) 최종 구성 요소는 디렉토리일 필요가 없습니다(최소한 경로 확인
과정이 우려된다. 다음과 같은 이유로 디렉토리 또는 비 디렉토리일 수 있습니다.
특정 시스템 호출의 요구 사항).

(II)
최종 구성 요소를 찾을 수 없는 경우 반드시 오류는 아닙니다. 어쩌면 우리는 단지
만들기. 최종 항목의 처리에 대한 자세한 내용은
특정 시스템 호출의 매뉴얼 페이지.

(iii)
심볼릭 링크인 경우 마지막 구성 요소에 문제가 있을 수도 있습니다.
그리고 그것을 따라해서는 안됩니다. 예를 들어 열 수(2) O_NOFOLLOW 플래그:
open(pathname = "a-symlink", flags = O_RDONLY | O_NOFOLLOW) 실패, 너무 많은 수준의
O_NOFOLLOW가 지정되었지만 경로 이름이
기호 링크

(iv)
사용자가 경로 이름을 입력할 때 실수를 하는 것은 일반적입니다. libexplain 라이브러리
ENOENT가 반환될 때 제안을 시도합니다. 예를 들면 다음과 같습니다.
open(pathname = "/usr/include/filecontrl.h", flags = O_RDONLY) 실패, 해당 파일이 없거나
경로 이름에 "filecontrl.h" 일반 파일이 없기 때문에 디렉토리(2, ENOENT)
"/ usr / include" 디렉토리, 대신 "fcntl.h" 일반 파일을 의미합니까?

(v) 최종 구성 요소가 다음과 다른 것이 요구될 수도 있습니다.
일반 파일:
readlink(경로 이름 = "just-a-file", 데이터 = 0x7F930A50, data_size = 4097) 실패,
경로 이름이 기호 링크가 아닌 일반 파일이기 때문에 잘못된 인수(22, EINVAL)

(VI)
FIXME: "t" 비트 처리.

제한
경로 이름 및 파일 이름과 관련하여 여러 가지 제한이 있습니다.

경로 이름 길이 제한
경로 이름에는 최대 길이가 있습니다. 경로 이름(또는 일부 중간
심볼릭 링크를 해결하는 동안 얻은 경로 이름)이 너무 깁니다. ENAMETOOLONG
오류가 반환됩니다("파일 이름이 너무 깁니다"). 시스템 제한이 어떻게 포함되는지 확인
오류 메시지에서.
open(경로명 = "매우 긴", 플래그 = O_RDONLY) 실패, 파일 이름이 너무 깁니다(36,
ENAMETOOLONG) 경로 이름이 시스템 최대 경로 길이(4096)를 초과하기 때문입니다.

파일 이름 길이 제한
일부 Unix 변형은 각 경로 구성 요소의 바이트 수에 제한이 있습니다.
그들 중 일부는 이것을 조용히 처리하고 일부는 ENAMETOOLONG을 제공합니다. 라이브러리 설명
라이브러리 사용 경로 설정(3) _PC_NO_TRUNC를 알려줍니다. 이 오류가 발생하면
libexplain 라이브러리는 오류 메시지에 한계를 명시합니다. 한계는
에서 얻은 경로 설정(3) _PC_NAME_MAX. 시스템 제한이 어떻게 포함되는지 확인
오류 메시지에서.
open(경로명 = "system7/only-had-14자", 플래그 = O_RDONLY) 실패, 파일
"only-had-36-characters" 구성 요소가 있으므로 이름이 너무 깁니다(14, ENAMETOOLONG).
시스템 제한보다 길다(14)

빈 경로 이름
원래 Unix에서 빈 경로 이름은 현재 디렉터리를 나타냅니다.
요즘 POSIX는 빈 경로 이름이 성공적으로 해결되어서는 안 된다고 선언합니다.
open(pathname = "", flags = O_RDONLY) 실패, 해당 파일이나 디렉터리가 없습니다(2,
ENOENT) POSIX가 빈 경로 이름을 해석해서는 안 된다고 규정하기 때문에
성공적으로

권한
파일의 허가 비트는 세 비트의 세 그룹으로 구성됩니다. 의 첫 번째 그룹
XNUMX은 호출 프로세스의 유효 사용자 ID가 해당 프로세스의 소유자 ID와 같을 때 사용됩니다.
파일. 파일의 그룹 ID가 다음 중 하나와 같을 때 XNUMX개의 두 번째 그룹이 사용됩니다.
호출 프로세스의 유효 그룹 ID이거나 호출 프로세스의 보조 그룹 ID 중 하나입니다.
호출 프로세스. 둘 다 성립하지 않으면 세 번째 그룹이 사용됩니다.
open(경로명 = "/ etc / passwd", 플래그 = O_WRONLY) 실패, 권한 거부(13,
EACCES) 프로세스에 "passwd" 일반에 대한 쓰기 권한이 없기 때문에
경로 이름의 파일 "/ 기타" 디렉토리, 프로세스 유효 UID 1000 "pmiller"
일반 파일 소유자 0 "루트"와 일치하지 않으므로 소유자 권한 모드 "rw-"
무시되고 다른 권한 모드는 "r--"이며 프로세스에 권한이 없습니다.
(DAC_OVERRIDE 기능이 없음)
대부분의 사용자가 이것이
권한 시스템이 작동하는 방식입니다. 특히: 소유자, 그룹 및 기타
권한은 배타적이며 함께 "OR"되지 않습니다.

이상한 흥미있는 시스템 통화


각 시스템 호출에 대한 특정 오류 처리기를 작성하는 프로세스는 종종 다음을 나타냅니다.
흥미로운 단점과 경계 조건, 또는 모호한 에르 노(3) 가치.

에노메디움, 아니 매질 발견
CD를 복사하는 행위가 이 논문의 제목의 출처였습니다.
$ dd if=/dev/cdrom of=fubar.iso
dd: "/dev/cdrom" 열기: 매체를 찾을 수 없음
$
저자는 왜 그의 컴퓨터가 심령술사와 같은 것은 없다고 말하는지 궁금했습니다.
중간. 많은 수의 영어 원어민이 그렇지 않다는 사실과는 별개로
"media"가 복수라는 사실을 알고 있어도 "medium"이 단수라는 것은 말할 것도 없고,
반환 스트러러(3) ENOMEDIUM은 거의 완전히 자유로울 정도로 간결하다.
내용.

인셀덤 공식 판매점인 열 수(2) ENOMEDIUM을 반환합니다. libexplain 라이브러리가 확장할 수 있다면 좋을 것입니다.
드라이브 유형에 따라 약간 다릅니다. 예를 들어:
... 플로피 드라이브에 디스크가 없기 때문에
... CD-ROM 드라이브에 디스크가 없기 때문에
... 테이프 드라이브에 테이프가 없기 때문에
... 카드 리더기에 메모리 스틱이 없기 때문에

그리고 그렇게 되었다...
open(경로 이름 = "/dev/cdrom", 플래그 = O_RDONLY) 실패, 매체를 찾을 수 없음(123,
ENOMEDIUM) CD-ROM 드라이브에 디스크가 없는 것 같습니다.
저자가 이전에 알지 못했던 트릭은 다음을 사용하여 장치를 여는 것이었습니다.
O_NONBLOCK 플래그를 사용하면 미디어가 없는 드라이브를 열 수 있습니다. 당신은 그때
기기별 발행 ioctls(2) 도대체 그것이 무엇인지 알아낼 때까지 요청하십시오. (아니다
이것이 POSIX인지 확실하지만 BSD 및 Solaris에서도 그렇게 작동하는 것으로 보입니다.
전에, 워딤(1) 출처.)

또한 문맥에서 "디스크"와 "디스크"의 다른 용도에 유의하십시오. CD 표준의 탄생
프랑스에서는 다른 모든 항목에 "k"가 있습니다.

오류, 나쁜 주소
포인터 인수를 사용하는 모든 시스템 호출은 EFAULT를 반환할 수 있습니다. libexplain 라이브러리
어떤 주장이 잘못되었는지 알아낼 수 있으며, 프로세스를 방해하지 않고 수행합니다.
(또는 스레드) 신호 처리.

사용 가능한 경우 민코어(2) 시스템 호출을 사용하여 메모리 영역이 유효한지 묻습니다.
세 가지 결과를 반환할 수 있습니다. 매핑되었지만 물리적 메모리에는 없음, 매핑 및 물리적 메모리에 없음
매핑되지 않은 메모리입니다. 포인터의 유효성을 테스트할 때 처음 두 개는 "예"입니다.
그리고 마지막은 "아니오"입니다.

포인터와 크기 대신에 C 문자열을 확인하는 것은 더 어렵습니다.
포인터가 있습니다. 크기를 결정하려면 NUL을 찾아야 하며,
segfault, catch-22.

이 문제를 해결하기 위해 libexplain 라이브러리는 이스타트(2) 시스템 호출(알려진
좋은 두 번째 인수) C 문자열의 유효성을 테스트합니다. 실패 반환 && errno == EFAULT
는 "아니오"이고 나머지는 "예"입니다. 이것은 물론 문자열을 PATH_MAX로 제한합니다.
문자이지만 일반적으로 libexplain 라이브러리에서는 문제가 되지 않습니다.
거의 항상 가장 긴 문자열에 관심이 있습니다.

엠파일, 너무 . 열 수 파일
이 오류는 프로세스에 이미 최대 파일 설명자가 열려 있을 때 발생합니다.
실제 제한이 인쇄되고 libexplain 라이브러리가 인쇄하려고 하면 열 수 없습니다.
파일 / proc 그것이 무엇인지 읽으십시오.
open_max = sysconf(_SC_OPEN_MAX);
이것은 그렇게 어렵지 않습니다. sysconf(3) 한계를 얻는 방법.

엔파일, 너무 . 열 수 파일 in 체계
이 오류는 열린 파일의 총 개수에 대한 시스템 제한이 있을 때 발생합니다.
도달했다. 이 경우 핸디가 없습니다 sysconf(3) 한계를 얻는 방법.

더 깊이 파고들면 Linux에 다음이 있음을 알 수 있습니다. / proc 우리가 읽을 수 있는 항목
이 값을 얻습니다. Catch-22: 파일 디스크립터가 부족하여 파일을 열 수 없습니다.
한계를 읽으십시오.

Linux에서는 이를 얻기 위한 시스템 호출이 있지만 [e]glibc 래퍼 기능이 없으므로
모든 것을 매우 신중하게 처리해야 합니다.

Explain_maxfile(무효)
{
#ifdef __linux__
구조체 __sysctl_args 인수;
int32_t 최대 파일;
크기_t 최대 파일_크기 = 크기(최대 파일);
정수 이름[] = { CTL_FS, FS_MAXFILE };
memset(&args, 0, sizeof(struct __sysctl_args));
args.name = 이름;
args.nlen = 2;
args.oldval = &maxfile;
args.oldlenp = &maxfile_size;
if (syscall(SYS__sysctl, &args) >= 0)
최대 파일 반환;
#endif
반환 -1;
}
이렇게 하면 사용 가능한 경우 오류 메시지에 제한이 포함될 수 있습니다.

에인발 "유효하지 않은 논쟁" vs 에노시스 "기능 지원 시행”
지원되지 않는 작업(예: 심볼릭 링크(2) FAT 파일 시스템에서) 보고되지 않음
하나의 시스템 호출에서 다음 시스템 호출까지 일관되게 EINVAL 또는
에노시스가 돌아왔습니다.

결과적으로 이러한 오류 사례를 올바르게 처리하려면 특히 주의해야 합니다.
EINVAL이 하나 이상의 시스템 호출 인수에 대한 문제를 참조할 수도 있기 때문입니다.

주의 사항 에르 노(3) is 지원 항상 세트
방법과 방법을 결정하기 위해 [e]glibc 소스를 읽어야 할 때가 있습니다.
일부 시스템 호출에 대해 오류가 반환될 때.

페프(3) 파일 번호(3)
종종 이러한 함수는 오류를 반환할 수 없다고 가정합니다. 다음 경우에만 해당됩니다.
전에, 흐름 인수는 유효하지만 유효하지 않은 것을 감지할 수 있습니다.
바늘.

fpathconf(3) 경로 설정(3)
반환 값 fpathconf(2)과하면 경로 설정(2) 합법적으로 -1일 수 있으므로 다음과 같습니다.
여부를 확인하는 데 필요한 에르 노(3) 명시적으로 설정되었습니다.

ioctls(2)
반환 값 ioctls(2) 합법적으로 -1일 수 있으므로 다음을 확인할 필요가 있습니다.
에르 노(3) 명시적으로 설정되었습니다.

읽기 디렉토리(3)
반환 값 읽기 디렉토리(3)은 오류와 파일 끝 모두에 대해 NULL입니다. 그것은
여부를 확인하는 데 필요한 에르 노(3) 명시적으로 설정되었습니다.

Setbuf(3) 세트 버퍼(3) 세트라인버프(3) setvbuf(3)
이 함수의 마지막을 제외한 모든 함수는 void를 반환합니다. 그리고 setvbuf(3) 다음과 같이 문서화됩니다.
오류 시 "XNUMX이 아닌 값"을 반환합니다. 여부를 확인하는 것이 필요합니다. 에르 노(3) 명시적으로
설정할 수 있습니다.

strtod(3) 스트톨(3) 스트톨드(3) 스트톨(3) 스트툴(3) 스트툴(3)
이러한 함수는 오류가 발생하면 0을 반환하지만 이는 또한 합법적인 반환 값이기도 합니다. 그것은
여부를 확인하는 데 필요한 에르 노(3) 명시적으로 설정되었습니다.

(3)
ANSI C 표준에서는 백업의 단일 문자만 요구하지만
[e]glibc는 더 많은 것을 허용하지만 이는 ENOMEM에서 실패할 수 있음을 의미합니다. 그것은 할 수 있습니다
다음과 같은 경우 EBADF에서도 실패합니다. fp 가짜다. 무엇보다 가장 어려운 것은 EOF 오류를 통과하면
반환이 발생하지만 errno가 설정되지 않았습니다.

libexplain 라이브러리는 다음과 같은 경우에도 이러한 모든 오류를 올바르게 감지합니다.
오류 값은 문서화되어 있지 않더라도 문서화되어 있습니다.

에노스PC, 아니 공간 왼쪽 (left) on 장치
이 오류가 파일 시스템의 파일을 참조하는 경우 libexplain 라이브러리는 마운트
문제가 있는 파일 시스템의 지점. 이것은 오류의 원인을 많이 만들 수 있습니다
더 명확합니다.
write(fildes = 1 "example", 데이터 = 0xbfff2340, data_size = 5) 실패, 남은 공간 없음
fildes("홈 /")가 없다
더 많은 데이터 공간
더 특별한 장치 지원이 추가됨에 따라 오류 메시지에 장치가 포함될 것으로 예상됩니다.
장치의 이름과 실제 크기.

에로프스, 읽기 전용 파일 체계
이 오류가 파일 시스템의 파일을 참조하는 경우 libexplain 라이브러리는 마운트
문제가 있는 파일 시스템의 지점. 이것은 오류의 원인을 많이 만들 수 있습니다
더 명확합니다.

더 특별한 장치 지원이 추가됨에 따라 오류 메시지에 장치가 포함될 것으로 예상됩니다.
이름과 유형.
open(pathname = "/dev/fd0", O_RDWR, 0666) 실패, 읽기 전용 파일 시스템(30, EROFS)
플로피 디스크에 쓰기 방지 탭이 설정되어 있기 때문에

...CD-ROM에 쓰기가 불가능하기 때문에
...메모리 카드에 쓰기 방지 탭이 설정되어 있기 때문에
...½인치 자기 테이프에는 쓰기 링이 없기 때문에

이름 변경
XNUMXD덴탈의 이름 변경(2) 시스템 호출은 파일의 위치나 이름을 변경하거나 이동하는 데 사용됩니다.
필요한 경우 디렉토리 사이에. 대상 경로 이름이 이미 존재하는 경우
원자적으로 대체되어 다른 프로세스가 시도하는 지점이 없습니다.
액세스하면 누락된 것을 찾을 수 있습니다.

그러나 제한 사항이 있습니다. 다른 디렉토리 위에 있는 디렉토리 이름만 변경할 수 있습니다.
대상 디렉터리가 비어 있지 않은 경우 디렉터리입니다.
이름 바꾸기(oldpath = "foo", newpath = "bar") 실패, 디렉터리가 비어 있지 않음(39,
ENOTEMPTY) newpath가 빈 디렉토리가 아니기 때문입니다. 즉, 항목이 포함되어 있습니다.
이것 말고도 "." 그리고 ".."
디렉토리가 아닌 것 위에 있는 디렉토리의 이름도 바꿀 수 없습니다.
rename(oldpath = "foo", newpath = "bar") 실패, 디렉토리가 아님(20, ENOTDIR)
oldpath는 디렉토리이지만 newpath는 디렉토리가 아닌 일반 파일이기 때문에
그 반대도 허용되지 않는다.
이름 바꾸기(oldpath = "foo", newpath = "bar") 실패, 디렉터리(21, EISDIR)
newpath는 디렉토리이지만 oldpath는 디렉토리가 아닌 일반 파일이기 때문입니다.

물론 이것은 libexplain 라이브러리의 작업을 더 복잡하게 만듭니다.
풀리다(2) 또는 rmdir(2) 시스템 호출은 다음과 같이 암시적으로 호출됩니다. 이름 변경(2), 그래서 모든
풀리다(2) 또는 rmdir(2) 오류도 감지하고 처리해야 합니다.

듀2
XNUMXD덴탈의 듀2(2) 시스템 호출은 다음을 참조하는 두 번째 파일 설명자를 만드는 데 사용됩니다.
첫 번째 파일 디스크립터와 동일한 객체. 일반적으로 이것은 셸 입력을 구현하는 데 사용됩니다.
및 출력 리디렉션.

재미있는 점은, 이름 변경(2) 파일 위에 원자적으로 이름을 바꿀 수 있습니다.
기존 파일을 제거하고 이전 파일을 제거합니다. 듀2(2) 이미 열려 있는 파일에 대해 이 작업을 수행할 수 있습니다.
기술자.

다시 한 번, 이것은 libexplain 라이브러리의 작업을 더 복잡하게 만듭니다. 가까운(2)
시스템 호출은 다음에 의해 암시적으로 호출됩니다. 듀2(2) 그리고 모든 가까운(2)의 오류는 다음과 같아야 합니다.
감지하고 처리합니다.

모험 IN IOCTL 고객지원


XNUMXD덴탈의 ioctls(2) 시스템 호출은 장치 드라이버 작성자에게 다음과 통신하는 방법을 제공합니다.
기존 커널 API에 맞지 않는 사용자 공간. 보다 ioctl_list(2).

디코딩 의뢰 넘버들
대충 보면 ioctls(2) 인터페이스는 크지만 유한한 것처럼 보일 것입니다.
가능한 수 ioctls(2) 요청. 각각 다른 ioctls(2) 요청이 유효하다
다른 시스템 호출이 있지만 유형 안전성이 전혀 없는 경우 - 컴파일러는 도움을 줄 수 없습니다.
프로그래머는 이러한 권리를 얻습니다. 이것이 아마도 동기였을 것이다. 티플러시(3)과하면
친구.

첫 인상은 디코딩할 수 있다는 것입니다. ioctls(2) 거대한 스위치를 사용한 요청
성명. 이것은 매우 빠르게 발견되기 때문에 실행 불가능한 것으로 판명되었습니다.
다양한 정의를 정의하는 필요한 모든 시스템 헤더를 포함하는 것은 불가능합니다. ioctls(2)
서로 잘 어울리기 힘들어서.

더 자세히 살펴보면 다양한 "비공개" 요청 번호와 장치가 있음을 알 수 있습니다.
드라이버 작성자는 이를 사용하는 것이 좋습니다. 이것은 훨씬 더 큰 가능성이 있음을 의미합니다.
즉시 명백한 것보다 모호한 요청 번호가 있는 요청 세트. 또한,
약간의 역사적 모호함도 있습니다.

우리는 이미 스위치가 비실용적이라는 것을 알고 있었지만 이제는
적절한 요청 이름과 설명 우리는 요청 번호뿐만 아니라
또한 파일 설명자.

구현 ioctls(2) libexplain 라이브러리 내 지원은 다음 테이블을 갖는 것입니다.
포인터 ioctls(2) 요청 기술자. 이러한 각각의 설명자는 선택 사항을 포함합니다.
명확화 함수에 대한 포인터.

각 요청은 실제로 별도의 소스 파일에서 구현되므로 필요한
인클루드 파일은 다른 사람들과 잘 놀아야 하는 의무에서 해방됩니다.

대표
libexplain 라이브러리의 철학은 최대한 많은 정보를 제공하는 것입니다.
시스템 호출의 정확한 표현을 포함하여 가능합니다. 의 경우
ioctls(2) 이것은 올바른 요청 번호(이름으로)와 올바른(또는
최소한 유용한) 세 번째 인수의 표현.

XNUMXD덴탈의 ioctls(2) 프로토타입은 다음과 같습니다.
int ioctl(int fildes, int 요청, ...);
유형 안전 경보가 울려야 합니다. [e]glibc 내부에서 이것은 설정되어 있습니다.
다양한 형태로:
int __ioctl(int fildes, int 요청, 긴 인수);
int __ioctl(int fildes, int 요청, void *arg);
그리고 Linux 커널 syscall 인터페이스는
asmlinkage long sys_ioctl(unsigned int fildes, unsigned int 요청, unsigned long
인수);
세 번째 인수의 극단적인 가변성은 libexplain 라이브러리가
세 번째 인수의 표현을 인쇄하려고 합니다. 그러나 일단 요청 번호
libexplain 라이브러리의 ioctl 테이블에 있는 각 항목에는
사용자 지정 print_data 기능(OO 수동으로 수행).

설명
사용할 설명을 결정하는 데 문제가 더 적습니다. 일단 요청번호
libexplain 라이브러리의 ioctl 테이블에 있는 각 항목에는 사용자 정의가 있습니다.
print_explanation 기능(다시 말하지만 OO는 수동으로 수행됨).

섹션 2 및 섹션 3 시스템 호출과 달리 대부분 ioctls(2) 요청에 오류가 없습니다.
문서화. 이것은 좋은 오류 설명을 제공하기 위해 커널을 읽을 필요가 있음을 의미합니다.
발견할 소스

· 무엇 에르 노(3) 값이 반환될 수 있으며,

· 각 오류의 원인.

커널 내에서 디스패치하는 함수 호출의 OO 특성 때문에 다음을 읽어야 합니다.
모든 그것을 구현하는 소스 ioctls(2) 일반 구현뿐만 아니라 요청. 그것
다른 커널에는 다른 오류 번호와 미묘하게 다른 오류가 있을 것으로 예상됩니다.
다른 오류 원인.

에인발 vs 에노티
의 상황은 더욱 나쁘다. ioctls(2) EINVAL을 사용하는 시스템 호출보다 요청
ENOTTY는 둘 다 다음을 나타내는 데 사용됩니다. ioctls(2) 요청이 부적절하다.
컨텍스트 및 때때로 ENOSYS, ENOTSUP 및 EOPNOTSUPP(소켓에 사용됨)
잘. Linux 커널 소스에 진보적임을 나타내는 주석이 있습니다.
정리가 진행 중입니다. 추가적인 혼란을 위해 BSD는 혼란에 ENIOIOCTL을 추가합니다.

결과적으로 이러한 오류 사례를 올바르게 처리하려면 특히 주의해야 합니다.
EINVAL이 하나 이상의 시스템 호출 인수에 대한 문제를 참조할 수도 있기 때문입니다.

intptr_t
C99 표준은 모든 포인터를 보유할 수 있도록 보장되는 정수 유형을 정의합니다.
대표성 손실 없이.

위의 함수 syscall 프로토타입은 더 잘 작성될 것입니다.
long sys_ioctl(unsigned int fildes, unsigned int 요청, intptr_t arg);
문제는 특정 장치 또는 파일 시스템에 의해 유발된 인지 부조화입니다.
ioctls(2) 다음과 같은 구현:
long vfs_ioctl(구조 파일 *filp, unsigned int cmd, unsigned long arg);
의 대다수 ioctls(2) 요청에는 실제로 int *arg 세 번째 인수가 있습니다. 하지만 그것을 가지고
선언된 long은 이것을 long *arg로 처리하는 코드로 이어집니다. 이것은 32비트에서 무해합니다.
(sizeof(long) == sizeof(int)) 그러나 64비트에서는 불쾌합니다(sizeof(long) != sizeof(int)).
엔디안 방식에 따라 원하는 값을 얻거나 얻지 못하지만 항상 얻을
메모리 낙서 또는 스택 낙서도 있습니다.

이 모든 것을 다음과 같이 작성하십시오.
int ioctl(int fildes, int 요청, ...);
int __ioctl(int 파일, int 요청, intptr_t 인수);
long sys_ioctl(unsigned int fildes, unsigned int 요청, intptr_t arg);
long vfs_ioctl(구조 파일 *filp, unsigned int cmd, intptr_t arg);
정수는 거의 같은 양을 나타내는 정수일 뿐임을 강조합니다.
항상 관련이 없는 포인터 유형입니다.

결론


libexplain을 사용하면 사용자가 좋아할 것입니다.

저작권


libexplain 버전 1.4
저작권 (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 피터 밀러

onworks.net 서비스를 사용하여 온라인으로 Explain_lca2010 사용


무료 서버 및 워크스테이션

Windows 및 Linux 앱 다운로드

  • 1
    통음
    통음
    SWIG는 소프트웨어 개발 도구입니다.
    C로 작성된 프로그램과
    다양한 고급 수준의 C++
    프로그래밍 언어. SWIG는 다음과 함께 사용됩니다.
    다른...
    SWIG 다운로드
  • 2
    WooCommerce Nextjs 반응 테마
    WooCommerce Nextjs 반응 테마
    React WooCommerce 테마,
    다음 JS, Webpack, Babel, Node 및
    GraphQL 및 Apollo를 사용한 Express
    고객. React의 WooCommerce 스토어(
    포함: 제품...
    WooCommerce Nextjs 반응 테마 다운로드
  • 3
    Archlabs_repo
    Archlabs_repo
    ArchLabs용 패키지 저장소 이것은
    가져올 수 있는 응용 프로그램

    https://sourceforge.net/projects/archlabs-repo/.
    그것은 OnWorks에서 호스팅되었습니다 ...
    archlabs_repo 다운로드
  • 4
    제퍼 프로젝트
    제퍼 프로젝트
    Zephyr 프로젝트는 새로운 세대입니다.
    실시간 운영체제(RTOS)
    여러 하드웨어 지원
    아키텍처. 그것은
    작은 크기의 커널...
    Zephyr 프로젝트 다운로드
  • 5
    SC콘
    SC콘
    SCons는 소프트웨어 구축 도구입니다.
    그것은에 대한 우수한 대안입니다
    고전적인 "만들기" 빌드 도구
    우리 모두는 알고 사랑합니다. 스콘은
    구현 ...
    SCons 다운로드
  • 6
    PSeInt
    PSeInt
    PSeInt는 의사 코드 해석기입니다.
    스페인어를 구사하는 프로그래밍 학생.
    주요 목적은 다음을 위한 도구가 되는 것입니다.
    기본을 배우고 이해하기
    개념...
    PSeInt 다운로드
  • 더»

Linux 명령

Ad