2012-04-25 2 views
2

따라서 성능 및 성능면에서 어셈블리에 간단한 서버를 작성합니다. 내가 아는 유일한 방법은 시스템 호출이다. (int 0x80을 통해) 분명히 어셈블 할 때 또는로드 할 때 할당 된 것보다 많은 메모리를 필요로 할 것이므로 읽어 보았고 주로 mmap()을 이해할 수 없기 때문에 sbrk()를 사용하기로 결정했습니다.syscall()을 어셈블리의 시스템 콜으로 사용

아무튼 Linux는 sbrk()에 대한 인터럽트를 제공하지 않으며 brk() 만 인터럽트를 제공합니다.

그래서 ... brk()을 사용하여 현재 프로그램 휴식을 찾으려면 어떻게해야합니까? getrlimit() 사용에 대해 생각했지만 getrlimit()에 전달할 리소스 (프로세스 ID)를 얻는 방법을 모르겠습니다. 아니면 sbrk()를 구현하는 다른 방법을 찾아야합니까?

+1

스택 오버플로에 오신 것을 환영합니다! "내가 아는 유일한 방법은 시스템 호출입니다.". 'sbrk'와 같은 라이브러리 호출도 있습니다. 아니면 "libc없이 어셈블리에서"의미합니까? –

+1

라이브러리 호출 방법을 잘 모르겠습니다. (그리고 아직도 방법을 모른다) 라이브러리 호출이 시스템 호출보다 빠르다고 생각하십니까? –

+0

'mmap'은 간단합니다. 작은 할당에도 좋지 않습니다. – doug65536

답변

1

sbrk 기능은 현재 값을 가져 와서 원하는 양을 수동으로 빼면 구현할 수 있습니다. 일부 시스템에서는 brk(0)을 사용하여 현재 값을 가져올 수 있고 다른 변수는 [_end의 주소로 초기화되는 변수]에서 추적 할 수 있습니다.이 값은 링커에서 초기 중단 값을 가리 키도록 설정됩니다.

이것은 매우 플랫폼 관련 사항이므로 YMMV입니다.

편집 : 리눅스는 :

그러나, 실제 리눅스 시스템 호출은 성공에 새로운 프로그램 중단을 반환합니다. 실패하면 시스템 호출은 현재 중단을 리턴합니다. glibc 래퍼 함수는 위에 설명 된 0과 -1 반환 값을 제공하기 위해 몇 가지 작업 (즉, 새 나누기가 addr보다 작은 지 여부를 확인)을 수행합니다.

그래서 어셈블리에서 현재 값을 얻기 위해 부조리 값을 0 또는 -1과 같이 호출 할 수 있습니다.

brk을 통해 할당 된 메모리를 "비울 수 없다"는 점에 유의하십시오. C로 작성된 malloc 함수를 링크하기 만하면됩니다. 어셈블리에서 C 함수를 호출하는 것은 어렵지 않습니다.

+0

아니면 OP가 메모리를 얻기 위해'MAP_ANONYMOUS | MAP_PRIVATE'를 사용하여'mmap' syscall을 만들 수 있고 그것을 풀어주기 위해'munmap'을 만들 수 있습니다. 이것은 사용자 공간에서 직접 메모리를 관리하는 것보다 비용이 많이 들지만 조립하는 것이 훨씬 쉽습니다 ... –

+2

"brk을 통해 할당 된 메모리를"비울 수 없다는 것을 알아 두십시오. " 그러나'man brk'은 "프로그램 중단을 늘리면 메모리를 프로세스에 할당하는 효과가 있으며 휴식을 줄이면 메모리가 할당 취소됩니다." 그렇다면 어떻게 brk을 통해 할당 된 메모리를 "자유롭게"할 수 없습니까? – automaton

+0

@automaton 메모리를 할당 한 후에 호출 한 다른 함수가 "더 위에"더 많은 메모리를 할당했을 수 있으므로 안전하지 않습니다. 전체 메모리 관리 시스템을 작성해야합니다. – Random832

0

출처 :

#include <unistd.h> 
#define SOME_NUMBER 8 
int main() { 
    void *ptr = sbrk(8); 
    return 0; 
} 

컴파일은 대한 시스템 호출이없는 ASM 코드

_main: 
Leh_func_begin1: 
    pushq %rbp 
Ltmp0: 
    movq %rsp, %rbp 
Ltmp1: 
    subq $16, %rsp 
Ltmp2: 
    movl $8, %eax 
    movl %eax, %edi 
    callq _sbrk 
    movq %rax, -16(%rbp) 
    movl $0, -8(%rbp) 
    movl -8(%rbp), %eax 
    movl %eax, -4(%rbp) 
    movl -4(%rbp), %eax 
    addq $16, %rsp 
    popq %rbp 
    ret 
Leh_func_end1: 

보고 있지만 해야

gcc -S -o test.S test.c 

그리고 조립 출력 옵션을 사용하여 여전히 전화를 걸 수 있습니다.

+0

fedora16/x86에서 정적 바이너리를 링크하고 objdumped했습니다. 나는 __sbrk 호출 __brk 전화를 brk syscall (syscall 45) –

+0

아마도,하지만 당신이 게시 한 여전히 _sbrk 연결된 외부 구현에 따라 –

+0

네, 언급 한대로 sbrk에 대한 시스템 호출이 없습니다 (적어도 내 컴퓨터에서는 유닉스 표준에서 시스템 호출로 제외되었다는 것을 합리적으로 확신 할 수있다.) 그래서 sbrk를 호출하려면 libc에 링크가 있어야 구현할 수있다. – lukecampbell