Перейти к содержанию

Системный вызов - аналог malloc


Гость

Рекомендуемые сообщения

Здравствуйте!

Некоторое время я пользовался для выделения памяти malloc'ом и ему подобными функциями. Но возникла необходимость добиться такого же эффекта при помощи не библиотечных функций, а системных вызовов. Насколько я понял, в Линухе для этих целей используется вызов brk, устанавливающий конец сегмента данных в новое значение. Означает ли увеличение сегмента данных, что можно считать выделенной область памяти между старым и новым адресами конца сегмента данных? Как в таком случае получить адрес начала этой области (без использования sbrk), или в общем случае - каким образом в произвольный момент времени можно получить адрес конца сегмента данных? Т.е. должно ли выделение памяти выглядеть вместо

p = malloc (0xffff);

так

p = <получить указатель на конец сегмента данных>;

brk (p + 0xffff);

?

И еще: man 2 brk

brk and sbrk are not defined in the C Standard and are deliberately from the POSIX.1 standard

Означает ли это, что существует еще один, соответствующий POSIX системный вызов для тех же целей?

Ссылка на комментарий
Поделиться на другие сайты

Вот очень неплохой пример (с Linux.com):

section	.bss

var1	resb	1

section	.text

;
;allocate memory
;

%define	LIMIT	0x4000000			; about 100Megs

	mov	ebx,0				; get bottom of data segment
	call	sys_brk

	cmp	eax,-1				; ok?
	je	erro1

	add	eax,LIMIT			; allocate +LIMIT memory
	mov	ebx,eax
	call	sys_brk
	
	cmp	eax,-1				; ok?
	je	erro1

	cmp	eax,var1+1			; has the data segment grown?
	je	erro1

;
;use allocated memory
;
						; now eax contains bottom of
						; data segment
	mov	ebx,eax				; save bottom
	mov	eax,var1			; eax=beginning of data segment
repeat:	
	mov	word	[eax],1			; fill up with 1's
	inc	eax
	cmp	ebx,eax				; current pos = bottom?
	jne	repeat

;
;free memory
;

	mov	ebx,var1			; deallocate memory
	call	sys_brk				; by forcing its beginning=var1

	cmp	eax,-1				; ok?
	je	erro2
Что непонятно - спрашивайте.

Цитата:

brk and sbrk are not defined in the C Standard and are deliberately from the POSIX.1 standard

Означает ли это, что существует еще один, соответствующий POSIX системный вызов для тех же целей?

Нет, это означает, что он только в POSIX и существует, а в стандарте С его нет.

Ссылка на комментарий
Поделиться на другие сайты

Да... Зря я так доверял печенью. Написал пост, потом гляжу - а я уж и аноним Smile

Спасибо за ответ. Только одно уточнение: перебивая фразу их мана, пропустил слово:

are deliberately excluded from the POSIX.1 standard

Вроде мелочь, а смысл не тот Smile

А то, что в Си-стандарте он не определен, а из ПОЗИКСа умышленно исключен, наводит на некоторые размышления Smile

Ссылка на комментарий
Поделиться на другие сайты

Ага... вот и вопросы появились...

Дайте, пожалуйста, ссылку на полный вариант приведенного кода (если она у Вас есть, конечно Smile). В частности, меня интересет функция sys_brk, исходя из того, что адрес ей передается в ebx, я могу предположить, что в ней и происходит обращение к системному вызову. Но и только - предположить Smile

Ссылка на комментарий
Поделиться на другие сайты

Нет, полной версии кода у меня нет. Но в данном случае, функция sys_brk просто показывает, что происходит обращение к системному вызову - не зацикливайтесь на регистрах, думаю и так понятно.

А чем не устраивает sbrk? Это, как написано в мане, не системный вызов, а оболочка к нему, но сильно это сути не меняет. Аналогичный вопрос и про malloc. Или речь об ассемблере без использования библиотеки С?

Ссылка на комментарий
Поделиться на другие сайты

1.

Цитата:

в данном случае, функция sys_brk просто показывает, что происходит обращение к системному вызову

Показывать-то показывает, но, например, следующий кусочек кода:

mov	ebx,0				; get bottom of data segment
call	sys_brk

Получить таким образом дно сегмента данных (согласно мана) можно именно используя sbrk:

data = sbrk (0);

А вот такое совсем не укладывается в синтаксис sbrk:

add	eax,LIMIT			; allocate +LIMIT memory
	mov	ebx,eax
	call	sys_brk

которому должно передаваться смещение относительно текущего конца сегмента, а не полный адрес...

Вот потому меня эта функция и заинтересовала...

2.

Цитата:

Или речь об ассемблере без использования библиотеки С?

Именно. Хочется получить возможно более маленький бинарник, причем - статически слинкованный. Как совместить эти два требования с использованием libc, я не представляю. А ведь системные вызовы ничуть не хуже...

Ссылка на комментарий
Поделиться на другие сайты

Сам не сталкивался, интересно стало. Вот что нашёл про sbrk():

#include <string.h>
#include <stdio.h>
void *sbrk(int);
main()
{
    unsigned int count = 100;
    char *ptr;
    ptr = sbrk(count);
    if (ptr == (char *)-1)
    {
        perror("No available space for sbrk\n");
        return;
    }
    strcpy(ptr, "String of data:");
    strcat(ptr, "another string added\n");
    fputs(ptr, stdout);
}

С этим всё просто. А вот как получить (а не установить) текущий адрес конца области данных с использованием только brk(), мне неизвестно.

Ссылка на комментарий
Поделиться на другие сайты

Благодарю за ответ.

Все равно ничего не получается Sad

Пойду почитаю исходники glibc, что за sbrk() такой...

Хотя все равно это кажется какой-то бессмыслицей: назначить адрес можно, а получить нельзя. Как мне кажется, смысл в таком может быть только в одном случае - если _все_ исполняемые файлы запускаются с фиксированными адресами конца .data, но это полная ерунда, IMHO

Ссылка на комментарий
Поделиться на другие сайты

Цитата:

если _все_ исполняемые файлы запускаются с фиксированными адресами конца .data, но это полная ерунда, IMHO

Конечно ерунда, я могу статически навыделять разный размер памяти.

Цитата:

Хотя все равно это кажется какой-то бессмыслицей: назначить адрес можно, а получить нельзя.

Действительно странно. Наверняка это можно сделать, но явно не средствами brk - он же статус возвращает, а не адрес.
Ссылка на комментарий
Поделиться на другие сайты

Цитата:

Конечно ерунда, я могу статически навыделять разный размер памяти.

Smile

Ну... можно запускать бинарник с начальным адресом .data = фиксированный конечный адрес - размер всего статически выделенного Smile

Цитата:

Наверняка это можно сделать, но явно не средствами brk - он же статус возвращает, а не адрес.

Ага. В man brk есть ссылка на getrlimit, но это вообще предел потребляемых ресурсов:

resource moust be one of:

...

RLIMIT_DATA

The maximum size of the process's data segment (initialized data, uninitialized data, and heap). This limit affects calls to brk() and sbrk(), which fail with the error ENOMEM upon encountering the soft limit of this resource

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
×
×
  • Создать...