2012-04-25 66 views
2

因此,作爲一項挑戰和性能,我正在編寫一個簡單的彙編服務器。我知道的唯一方法是通過系統調用。 (通過int 0x80)顯然,我需要比在彙編或加載時分配更多的內存,所以我讀了,並決定我想使用sbrk(),主要是因爲我不明白mmap():pLinux sbrk()作爲彙編中的系統調用

無論如何,Linux不會爲sbrk(),僅提供brk()中斷。

所以...我如何找到當前程序中斷使用brk()?我想過使用getrlimit(),但我不知道如何獲取資源(我猜想的進程ID)傳遞給getrlimit()。或者我應該找到其他方法來實現sbrk()?

+1

歡迎來到Stack Overflow! 「我知道的唯一方法就是通過系統調用。」也有圖書館電話,如'sbrk'。或者你的意思是「在沒有libc的彙編中」? – 2012-04-25 19:16:44

+1

我不確定如何進行圖書館電話。 (並且仍然不知道如何)你認爲庫調用比系統調用更快嗎? – 2012-04-25 19:44:50

+0

'mmap'很簡單。儘管如此,小分配並不好。 – doug65536 2017-10-26 07:37:44

回答

1

sbrk函數可以通過獲取當前值並手動減去所需的數量來實現。有些系統允許您通過brk(0)獲取當前值,其他人則通過變量[使用地址_end進行初始化,該變量由鏈接器設置爲指向初始中斷值]跟蹤它。

這是一個非常特定於平臺的事情,所以YMMV。

編輯:在Linux上:

然而,實際的Linux系統調用成功,則返回新節目間斷。失敗時,系統調用返回當前中斷。 glibc包裝函數執行一些工作(即,檢查新中斷是否小於addr)以提供上述的0和-1返回值。

因此,從組裝,你可以用一個荒謬的值稱呼它爲0或-1,以獲得當前值。

要知道,你不能「免費」的內存通過BRK分配的 - 你可能只想在用C編寫彙編語言中調用C函數malloc函數鏈接並不難。

+0

或者OP可以通過MAP_ANONYMOUS | MAP_PRIVATE來使'mmap'系統調用來獲取內存,並使用'munmap'來釋放它。這比自己在用戶空間管理你的內存比較昂貴,但會是一個更容易從裝配做... – 2012-04-27 04:23:17

+2

「要知道,你不能‘免費’的內存通過BRK分配」。但是'man brk'卻說:「增加程序中斷會爲進程分配內存,減少中斷釋放內存」。那麼,你怎麼不能「釋放」通過brk分配的內存呢? – automaton 2015-07-28 08:00:54

+0

@automaton這樣做並不安全,因爲在分配內存之後調用的其他函數可能會在「之上」分配更多內存。你必須編寫一個完整的內存管理系統。 – Random832 2015-07-29 21:44:56

0

來源:按照大會輸出選項使用

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

編譯

gcc -S -o test.S test.c 

然後看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: 

沒有系統調用,但你應該還能撥打電話

+0

我將fedora16/x86上的二進制靜態鏈接和objdumped鏈接起來。我看到__sbrk調用__brk,它調用了brk系統調用(syscall 45) – 2012-04-25 19:36:15

+0

也許,但是你發佈的內容仍然取決於_sbrk的外部實現在 – 2012-04-25 19:37:42

+0

中鏈接是的,正如我所提到的,沒有系統調用sbrk(至少在我的機器上,我有理由確定它作爲系統調用被排除在Unix標準之外),所以爲了調用sbrk,你需要在'libc'中鏈接它,應該實現它。 – lukecampbell 2012-04-25 20:00:38