gpt4 book ai didi

linux - 为什么我的进程需要很长时间才能终止?

转载 作者:太空宇宙 更新时间:2023-11-04 03:37:17 25 4
gpt4 key购买 nike

基本上我在 PowerPC (Freescale e500mc) 上使用 Linux 2.6.34。我有一个进程(一种内部开发的 VM),使用大约 2.25 G 的 mlocked VM。当我杀死它时,我注意到需要 2 分钟以上才能终止。

我调查了一下。首先,我关闭了所有打开的文件描述符,但这似乎没有什么区别。然后我在内核中添加了一些 printk,通过它我发现所有延迟都来自内核解锁我的 VMA。各个页面的延迟是一致的,我通过反复检查/proc/meminfo 中的锁定页面计数来验证这一点。我检查过分配那么多内存的程序,一旦我向它们发出信号,它们就会立即死亡。

你认为我现在应该检查什么?感谢您的回复。

编辑:我必须找到一种方法来分享有关该问题的更多信息,因此我编写了以下程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>

#define MAP_PERM_1 (PROT_WRITE | PROT_READ | PROT_EXEC)
#define MAP_PERM_2 (PROT_WRITE | PROT_READ)

#define MAP_FLAGS (MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE)

#define PG_LEN 4096
#define align_pg_32(addr) (addr & 0xFFFFF000)
#define num_pg_in_range(start, end) ((end - start + 1) >> 12)

inline void __force_pgtbl_alloc(unsigned int start)
{
volatile int *s = (int *) start;
*s = *s;
}

int __map_a_page_at(unsigned int start, int whichperm)
{
int perm = whichperm ? MAP_PERM_1 : MAP_PERM_2;

if(MAP_FAILED == mmap((void *)start, PG_LEN, perm, MAP_FLAGS, 0, 0)){
fprintf(stderr,
"mmap failed at 0x%x: %s.\n",
start, strerror(errno));
return 0;
}

return 1;
}

int __mlock_page(unsigned int addr)
{
if (mlock((void *)addr, (size_t)PG_LEN) < 0){
fprintf(stderr,
"mlock failed on page: 0x%x: %s.\n",
addr, strerror(errno));
return 0;
}

return 1;
}

void sigint_handler(int p)
{
struct timeval start = {0 ,0}, end = {0, 0}, diff = {0, 0};
gettimeofday(&start, NULL);
munlockall();
gettimeofday(&end, NULL);
timersub(&end, &start, &diff);

printf("Munlock'd entire VM in %u secs %u usecs.\n",
diff.tv_sec, diff.tv_usec);

exit(0);
}

int make_vma_map(unsigned int start, unsigned int end)
{
int num_pg = num_pg_in_range(start, end);

if (end < start){
fprintf(stderr,
"Bad range: start: 0x%x end: 0x%x.\n",
start, end);
return 0;
}

for (; num_pg; num_pg --, start += PG_LEN){
if (__map_a_page_at(start, num_pg % 2) && __mlock_page(start))
__force_pgtbl_alloc(start);
else
return 0;
}

return 1;
}

void display_banner()
{
printf("-----------------------------------------\n");
printf("Virtual memory allocator. Ctrl+C to exit.\n");
printf("-----------------------------------------\n");
}

int main()
{
unsigned int vma_start, vma_end, input = 0;
int start_end = 0; // 0: start; 1: end;

display_banner();

// Bind SIGINT handler.
signal(SIGINT, sigint_handler);

while (1){
if (!start_end)
printf("start:\t");
else
printf("end:\t");

scanf("%i", &input);

if (start_end){
vma_end = align_pg_32(input);
make_vma_map(vma_start, vma_end);
}
else{
vma_start = align_pg_32(input);
}
start_end = !start_end;
}

return 0;
}

正如您所看到的,程序接受虚拟地址范围,每个范围由开始和结束定义。然后,通过向相邻页面授予不同的权限,将每个范围进一步分割为页面大小的 VMA。中断(使用 SIGINT)程序会触发对 munlockall() 的调用,并且会适当记录该过程完成的时间。

现在,当我在 Linux 版本为 2.6.34 的 freescale e500mc 上在 0x30000000-0x35000000 范围内运行它时,我得到的 munlockall() 总时间几乎为 45 秒。但是,如果我以随机顺序(即不一定增加地址)对较小的起始结束范围执行相同的操作,使得页面总数(和锁定的 VMA)大致相同,则观察到 munlockall() 总时间不超过 4 秒。

我在使用 Linux 2.6.34 的 x86_64 上尝试了同样的操作,并且我的程序根据 -m32 参数进行编译,虽然变化不像 ppc 那么明显,但第一种情况仍然是 8 秒,第二种情况不到一秒。

我一方面在 Linux 2.6.10 上尝试过该程序,另一方面在 3.19 上尝试过,似乎这些巨大的差异在那里不存在。更重要的是,munlockall() 总是在一秒内完成。

因此,无论问题是什么,似乎只存在于 Linux 内核 2.6.34 版本周围。

最佳答案

你说虚拟机是内部开发的。这是否意味着您可以访问源代码?我首先检查它是否有任何东西可以阻止它立即终止以避免数据丢失。

否则,您可以尝试提供更多信息吗?您可能还想查看:https://unix.stackexchange.com/因为它们更适合帮助解决 Linux 内核可能遇到的任何问题。

关于linux - 为什么我的进程需要很长时间才能终止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31137438/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com