: 당신이 볼 수 있듯이, 매개 변수가 HTML 테이블에서 사람과 일치
off_t lseek(int fd, off_t offset, int whence);
Linux의 표준 프로그래밍 언어는 C입니다.이 때문에 시스템 호출의 가장 좋은 설명은 호출 할 C 함수로 표시됩니다. C 함수로서의 설명과이를 어셈블리에서 실제 시스템 호출에 매핑하는 방법에 대한 지식이 있으면 원하는 시스템 호출을 쉽게 사용할 수 있습니다.
먼저 C 프로그래머에게 표시되는 모든 시스템 호출에 대한 참조가 필요합니다. 내가 아는 가장 좋은 것은 Linux man-pages project이며, 특히 system calls 섹션입니다.
write
시스템 호출은 예제의 시스템 호출을 예로 들어 봅시다. 보시다시피 첫 번째 매개 변수는 부호가있는 정수이며 일반적으로 open
시스템 호출에 의해 반환 된 파일 설명 자입니다. 이러한 파일 설명자는 부모 프로세스에서 상속되었을 수도 있습니다. 일반적으로 처음 세 파일 설명자 (0 = stdin, 1 = stdout, 2 = stderr)에서 발생합니다. 두 번째 매개 변수는 버퍼에 대한 포인터이고 세 번째 매개 변수는 버퍼 크기 (부호없는 정수)입니다. 마지막으로 함수는 부호있는 정수 (기록 된 바이트 수 또는 음수)를 반환합니다.
이제 이것을 실제 시스템 호출에 매핑하는 방법은 무엇입니까? 32 비트 x86에서 시스템 호출을 수행하는 방법에는 여러 가지가 있습니다 (레지스터 이름을 기반으로 사용하는 것일 수 있습니다). 64 비트 x86에서는 32 비트 모드로 어셈블하고 32 비트 실행 파일을 연결해야합니다 (다른 방법이 잘못 될 수있는 예에 대해서는 this question을 참조하십시오). 가장 오래된 것 중 가장 간단하고 가장 느린 것은 32 비트 x86에서 int $0x80
메서드입니다.
는 int $0x80
방법의 경우, %eax
에서 시스템 콜 번호를 넣어의 매개 변수 %ebx
, %ecx
, %edx
, %esi
, %edi
및 %ebp
, 순서입니다. 그런 다음 int $0x80
을 호출하고 시스템 호출의 반환 값은 %eax
입니다. 이 반환 값은 이고 다른 참조 번호는입니다. 참조는 C 라이브러리가이를 리턴하는 방법을 보여 주지만 시스템 호출은 오류시 -errno
을 리턴합니다 (예 : -EINVAL
). 이 경우 C 라이브러리는 errno
으로 이동하고 -1
을 반환합니다. 자세한 내용은 syscalls(2) 및 intro(2)을 참조하십시오.
그래서, write
예를 들어, 당신은 (%eax
에서 write
시스템 호출 번호, %ebx
의 첫 번째 매개 변수 (파일 기술자 번호), %ecx
에서 두 번째 매개 변수 (문자열 포인터), 그리고 세 번째 매개 변수를 둘 것 문자열의 길이)는 %edx
입니다. 시스템 콜은 %eax
에 쓰여진 바이트 수를 반환하거나 에러 번호를 무효화합니다 (반환 값이 -1과 -4095 사이 인 경우 부정 된 에러 번호).
마지막으로 어떻게 시스템 호출 번호를 찾으십니까? 그들은 /usr/include/linux/unistd.h
에서 찾을 수 있습니다. 내 시스템에는 /usr/include/asm/unistd.h
이 포함되어 있으며, 마지막으로 /usr/include/asm/unistd_32.h
이 포함되어 숫자가 있습니다 (write
의 경우 __NR_write
은 4
입니다). /usr/include/linux/errno.h
에서 오는 오류 번호도 마찬가지입니다 (내 시스템에서 포함 체인을 추적 한 후 첫 번째 코드는 /usr/include/asm-generic/errno-base.h
이고 나머지는 /usr/include/asm-generic/errno.h
). 다른 상수 나 구조체를 사용하는 시스템 호출의 경우 해당 문서에서 해당 정의를 찾으려면 어떤 헤더를 봐야하는지 알려줍니다. 내가 말했듯이
지금, int $0x80
는 가장 오래되고 가장 느린 방법입니다. 최신 프로세서에는보다 빠른 특수 시스템 호출 명령어가 있습니다. 커널을 사용하기 위해 하드웨어에서 사용할 수있는 최상의 방법을 사용하여 시스템 호출을 수행 할 수있는 함수를 사용하여 가상 동적 공유 객체 (vDSO
, 공유 라이브러리와 같지만 메모리에만 있음)를 사용할 수 있습니다. 또한 시스템 호출을하지 않고도 현재 시간을 알 수있는 특별한 기능을 제공합니다. 물론, 동적 링커를 사용하지 않는다면 사용하기가 조금 더 어렵습니다.
또 다른 구식 방법 인 vsyscall
은 vDSO
과 유사하지만 고정 주소에서 단일 페이지를 사용합니다. 이 방법은 더 이상 사용되지 않으며, 최근 커널을 사용하고 더 최근의 커널에서 부팅 할 때 비활성화 할 수 있으며 나중에 제거 될 수있는 경우 시스템 로그에 경고가 표시됩니다. 사용하지 마십시오.
물론 Google에서 각 검색을 수행하거나 소스 코드를 검색하여 구현하는 경우에도 직접 사용 된 사례를 찾을 수 있습니다. 내 게시물의 요점은 검색 및 일부 좋은 치트 시트와 분석을 건너는 것입니다. 감사. –