[英]Why my implementation of sbrk system call does not work?
I try to write a very simple os to better understand the basic principles. 我尝试编写一个非常简单的操作系统,以更好地理解基本原理。 And I need to implement user-space malloc.
而且我需要实现用户空间malloc。 So at first I want to implement and test it on my linux-machine.
因此,起初我想在我的linux机器上实现并测试它。
At first I have implemented the sbrk() function by the following way 首先,我通过以下方式实现了sbrk()函数
void* sbrk( int increment ) {
return ( void* )syscall(__NR_brk, increment );
}
But this code does not work. 但是此代码不起作用。 Instead, when I use sbrk given by os, this works fine.
相反,当我使用os给定的sbrk时,这可以正常工作。
I have tryed to use another implementation of the sbrk() 我试图使用sbrk()的另一种实现
static void *sbrk(signed increment)
{
size_t newbrk;
static size_t oldbrk = 0;
static size_t curbrk = 0;
if (oldbrk == 0)
curbrk = oldbrk = brk(0);
if (increment == 0)
return (void *) curbrk;
newbrk = curbrk + increment;
if (brk(newbrk) == curbrk)
return (void *) -1;
oldbrk = curbrk;
curbrk = newbrk;
return (void *) oldbrk;
}
sbrk invoked from this function 从此函数调用的sbrk
static Header *morecore(unsigned nu)
{
char *cp;
Header *up;
if (nu < NALLOC)
nu = NALLOC;
cp = sbrk(nu * sizeof(Header));
if (cp == (char *) -1)
return NULL;
up = (Header *) cp;
up->s.size = nu; // ***Segmentation fault
free((void *)(up + 1));
return freep;
}
This code also does not work, on the line (***) I get segmentation fault. 此代码也不起作用,在行(***)上出现分段错误。 Where is a problem ?
哪里有问题?
Thanks All. 谢谢大家 I have solved my problem using new implementation of the sbrk.
我已经使用sbrk的新实现解决了我的问题。 The given code works fine.
给定的代码工作正常。
void* __sbrk__(intptr_t increment)
{
void *new, *old = (void *)syscall(__NR_brk, 0);
new = (void *)syscall(__NR_brk, ((uintptr_t)old) + increment);
return (((uintptr_t)new) == (((uintptr_t)old) + increment)) ? old :
(void *)-1;
}
The first sbrk
should probably have a long increment
. 第一个
sbrk
可能应具有long increment
。 And you forgot to handle errors (and set errno
) 而且您忘记了处理错误(并设置了
errno
)
The second sbrk
function does not change the address space (as sbrk
does). 第二个
sbrk
函数不会更改地址空间 (就像sbrk
一样)。 You could use mmap
to change it (but using mmap
instead of sbrk
won't update the kernel's view of data segment end as sbrk
does). 你可以使用
mmap
改变它(但使用mmap
而不是sbrk
将不会更新数据片段结尾为内核的观点sbrk
一样)。 You could use cat /proc/1234/maps
to query the address space of process of pid 1234). 您可以使用
cat /proc/1234/maps
查询pid 1234进程的地址空间。 or even read (eg with fopen
& fgets
) the /proc/self/maps
from inside your program. 甚至从程序内部读取(例如,使用
fopen
和fgets
) /proc/self/maps
。
BTW, sbrk
is obsolete (most malloc implementations use mmap
), and by definition every system call (listed in syscalls(2) ) is executed by the kernel (for sbrk
the kernel maintains the "data segment" limit!). 顺便说一句,
sbrk
已过时(大多数malloc实现使用mmap
),并且根据定义,每个系统调用 (在syscalls(2)中列出)均由内核执行(对于sbrk
, 内核保持“数据段”限制!)。 So you cannot avoid the kernel, and I don't even understand why you want to emulate any system call. 因此,您无法避免使用内核,我什至不理解为什么要模拟任何系统调用。 Almost by definition, you cannot emulate syscalls since they are the only way to interact with the kernel from a user application.
几乎根据定义, 您无法模拟系统调用,因为它们是从用户应用程序与内核进行交互的唯一方法。 From the user application, every syscall is an atomic elementary operation (done by a single
SYSENTER
machine instruction with appropriate contents in machine registers). 在用户应用程序中,每个系统调用都是原子性的基本操作(由一条
SYSENTER
机器指令完成,并在机器寄存器中包含适当的内容)。
You could use strace(1) to understand the actual syscalls done by your running program. 您可以使用strace(1)来了解正在运行的程序执行的实际syscall。
BTW, the GNU libc
is a free software . 顺便说一句, GNU
libc
是一个免费软件 。 You could look into its source code. 您可以查看其源代码。 musl-libc is a simpler libc and its code is more readable.
musl-libc是更简单的libc ,其代码更易读。
At last compile with gcc -Wall -Wextra -g
and use the gdb
debugger (you can even query the registers, if you wanted to). 最后,使用
gcc -Wall -Wextra -g
编译并使用gdb
调试器(如果需要,您甚至可以查询寄存器)。 Perhaps read the x86/64-ABI specification and the Linux Assembly HowTo . 也许阅读x86 / 64-ABI规范和Linux Assembly HowTo 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.