How to Dynamically Allocate Memory Using Assembly and System Calls Under Linux

How to Dynamically Allocate Memory Using Assembly and System Calls Under Linux

brk(2). And take a look at ELF.

Do linux read/write system calls use dynamic memory allocation?

No. If you look for syscalls in the Linux kernel source (I used grep -rn SYSCALL_DEFINE.*write to find read/write), you can see the source for yourself:

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
struct fd f = fdget_pos(fd);
ssize_t ret = -EBADF;

if (f.file) {
loff_t pos = file_pos_read(f.file);
ret = vfs_read(f.file, buf, count, &pos);
if (ret >= 0)
file_pos_write(f.file, pos);
fdput_pos(f);
}
return ret;
}

SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
size_t, count)
{
struct fd f = fdget_pos(fd);
ssize_t ret = -EBADF;

if (f.file) {
loff_t pos = file_pos_read(f.file);
ret = vfs_write(f.file, buf, count, &pos);
if (ret >= 0)
file_pos_write(f.file, pos);
fdput_pos(f);
}

return ret;
}

Note that system call definitions can be different across platforms: they don't have to be identical for all platforms. In fact, many platforms have system calls only supported on a handful of architectures.

In your case (i.e. sockets), there is a per-socket buffer that is pre-allocated, likely via dynamic allocation. It's easy to check what the size is for this buffer.

Originally posted by saeedn:

/proc/sys/net/ipv4/tcp_rmem (for read)
/proc/sys/net/ipv4/tcp_wmem (for write)

There are also c snippets at the links above to extract those values in code.

If you try to write massive messages that exceed this buffer size, you'll need to break them up. In general, when writing to a socket, you'll want to create your own write()-wrapper to confirm if all data was written, or if you need to call write() again with a portion of the leftover data, etc.

As far as performance hits for dynamic memory allocation goes, once your socket has been created, that part is done. The greater bottleneck for throughput will be handling the I/O with the socket.

Dynamically allocate memory in Assembly?

The other way is to define static array as large as possible and write your own malloc/free subroutines. It is simple especially if there is no multithreading or other kind of shared usage of the allocated blocks. You keep the address of first empty block and in the beginning of each block is stored the size of block and address of next free block.

PS: allocated (reserved) blocks also contain block size as prefix. The address of next block is not used here and can be 0 as flag for "reserved" memory. More simple solution is to have only block size and flag free/used_block but in this way you have to scan multiple reserved blocks until reaching free block which is slower than a chain of only free blocks.

Can we do dynamic memory allocation, without system calls?

Can we do dynamic memory allocation, without system calls?

In practice, for most (but not all) operating systems, yes.

Specifically, if you reserve a huge area in your ".bss" section, then most operating systems won't allocate physical RAM for that area until its written to, and you can implement some kind of heap ("malloc()") that uses the reserved huge area.

Note: while this can avoid switching to/from kernel for system calls, it won't avoid switching to/from kernel for page faults.

I know malloc uses brk() or mmap() system calls to allocate memory.

That's a "language run-time specific" thing. There's no reason (for a language like C) the standard library can't do the same "huge reserved section" trick; and no reason you can't write a program that doesn't use "malloc()" at all (the program I'm currently writing in C does this because "malloc()" is a nasty piece of brokenness), and no reason for a different language (e.g. maybe something stack-based like LISP?) to have anything like the horrible POSIX/C mess.

Heap Memory Allocation in ARM64 Assembly without the C Standard Library

mmap with MAP_ANONYMOUS is preferred to sbrk/brk for most purposes in modern programs. Use munmap to free.

By the way, brk can deallocate memory; simply pass an address lower than the current break point. But this does limit you to freeing in a last-in-first-out fashion.

How to properly pass buffer pointers to Linux system calls in x86_64 assembly?

The actual problem is not with the buffer but with its length. Notice in the prototype you have socklen_t *addrlen so that should be a pointer. The value 15 that you pass is not a pointer hence the -EFAULT.

You should change the .length: equ $-ip_buff to ip_length: dd $-ip_buff and then use syscall getpeername,r12,ip_buff,ip_length



Related Topics



Leave a reply



Submit