我很遗憾在问到这个问题时会问这个问题,但我无法从他们那里得到澄清.所以我要问以下相关问题来区分系统调用(模式切换)和上下文切换
为什么在进行调用的进程的上下文必须保存然后重新加载时,系统调用不需要上下文切换.是否只是因为根据上下文切换的定义,必须对另一个进程进行切换.
在进行系统调用时,内核在"用户上下文"中执行是什么意思.
系统调用不需要上下文切换,但它取决于操作系统,并且在系统调用期间可能会发生上下文切换.我想知道在系统调用时发生上下文切换的情况会发生什么.任何例子?
为什么不alloca检查它是否可以分配内存?
来自man 3 alloca:
如果分配导致堆栈溢出,则程序行为未定义....如果无法扩展堆栈帧,则没有错误指示.
为什么alloca不能/不能检查它是否可以分配更多内存?
我理解的方式是alloca在堆栈上分配内存时在堆栈上(s)brk分配内存.来自https://en.wikipedia.org/wiki/Data_segment#Heap:
堆区域由malloc,calloc,realloc和free管理,可以使用brk和sbrk系统调用来调整其大小
来自man 3 alloca:
alloca()函数在调用者的堆栈帧中分配空间的大小字节.
并且堆栈和堆在收敛方向上增长,如此Wikipedia图中所示:
(上图来自Dougimed的Wikimedia Commons,发布于CC BY-SA 3.0)
现在,这两个alloca并(s)brk返回一个指向新分配内存的开始,这意味着它们必须知道哪里栈/堆结束当前时刻.的确,来自man 2 sbrk:
以增量0调用sbrk()可用于查找程序中断的当前位置.
因此,他们理解它,检查是否alloca可以分配所需的内存,实质上归结为检查堆栈的当前末端和堆的当前末尾之间是否有足够的空间.如果在堆栈上分配所需的内存会使堆栈到达堆,则分配失败; 否则,它会成功.
那么,为什么不能使用这样的代码来检查是否alloca可以分配内存?
void *safe_alloca(size_t size)
{
if(alloca(0) - sbrk(0) < size) {
errno = ENOMEM;
return (void *)-1;
} else {
return alloca(size);
}
}
Run Code Online (Sandbox Code Playgroud)
这对我来说更加困惑,因为显然(s)brk可以做这样的检查.来自man 2 …
我的测试代码显示,在free()程序退出之后和之前,堆内存都返回给操作系统。我使用htop(与 相同top)来观察行为。我的 glibc 版本是ldd (Ubuntu GLIBC 2.31-0ubuntu9.9) 2.31.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFSIZE 10737418240
int main(){
printf("start\n");
u_int32_t* p = (u_int32_t*)malloc(BUFSIZE);
if (p == NULL){
printf("alloc 10GB failed\n");
exit(1);
}
memset(p, 0, BUFSIZ);
for(size_t i = 0; i < (BUFSIZE / 4); i++){
p[i] = 10;
}
printf("before free\n");
free(p);
sleep(1000);
printf("exit\n");
}
Run Code Online (Sandbox Code Playgroud)
为什么会出现这个问题为什么 free() 函数不将内存返回给操作系统?观察到与我相反的行为?OP也使用linux,问题是在2018年提出的。我错过了什么吗?