[Pthread] Linux中的内存管理(一)--Paging

本文深入浅出地介绍了Linux操作系统在IA-32架构下如何管理内存。从硬件层面出发,探讨了分段机制和分页机制,并详细解释了Linux如何采用分页机制进行内存管理,同时兼顾与Intel平台的兼容性。
前几次我们分析了程序是如何在Linux上被加载运行的。这次我们尽量简洁的分析一下在Linux中,程序是如何使用内存,而系统又是怎样管理内存的。

内存访问和管理是一个跨越应用程序,操作系统,硬件平台的一个复杂的过程。虽然过程很复杂,我们还是尝试着去理解一下。

1. IA-32架构中的内存管理机制

我们从硬件开始吧,内存归根结底是硬件,内存(Random Access Memory)在加电的情况下,在地址总线上放上要读取/写入的地址,然后就可以在控制信号的帮助下,从数据总线上得到/写入相应地址的数据了。数据总线的宽度通常与处理器寄存器位数相同(这也是8位机,16位机等叫法的由来)。这是内存的硬件特征。

有了这么个硬件内存,系统应该怎么使用呢?我们来看看硬件平台是如何设计的
最开始的时候,如在Intel 8086上,使用的是被后来称为"实地址"的模式。在实模式下,直接在程序中使用物理地址来访存,因为程序所使用的物理地址可能冲突,这给程序开发和运行带来了很大的困难。那个时候的程序员在开发应用程序的时候,如何合理有效的使用内存是相当重要的话题。
此后,为了便于程序的开发,提高系统的多道任务和系统的稳定性。从80286开始,处理器提供了"保护模式",逐渐引入了段,页等内存管理机制。最先引入的是分段处理机制,在分段处理中,系统有个全局的GDT(Global Descriptor Table),而每个进程能够有自己的LDT(Local Descriptor Table),程序也被分为数据段,代码段,堆栈段,其基地址分别存储在不同的段寄存器中。程序中使用的是逻辑地址,而逻辑地址通过段基地址+偏移量的方式映射成为物理地址。这样一来进程使用的地址空间就被不同的段基地址分开了。
但是分段还是会有一些问题,比如段不定长,但段内物理内存要求连续等。所以之后系统又引入了分页机制。在分页机制中,内存被分成了固定大小的页(常见的是4KB)。不同的进程通过使用不同的内存页来分开,因为页大小固定,所以方便了系统的管理和维护。

在常见的IA-32体系下,同时使用了段页式内存管理。其规定程序中使用的是逻辑地址,逻辑地址通过段映射机制变成线性地址,线性地址通过页映射机制最后变成物理地址。即:
        逻辑地址---->段映射---->线性地址---->页映射---->物理地址
当然这只是硬件厂商的设计,他们按照这个设计来提供了辅助的硬件,如段寄存器, MMU, TLB等。在这个硬件平台上运行的软件(操作系统)也受这个设计的限制,或者说从这个设计中得益。

2. Linux中的内存管理机制
Linux(for IA-32)基本上遵循了上一节提到的设计。当然这样做的目的也是为了充分利用硬件,发挥硬件的最大效率。
首先在Linux中程序使用的是也是逻辑地址,逻辑地址空间是每个进程独占的,其大小通常为4G,也常常被称为虚存。虚存的大小与物理内存的大小并没有关系。即一个使用了1G虚存的程序,也可以运行在只有256M物理内存的机器上面。
接着在Linux中也使用了段映射,不过在Liunx中所有的段寄存器都指向一个相同的段地址范围,即所有进程的线性地址是相同的,都是从0x00000000到0xffffffff(0-4G)。简单点说就是在Linux中段映射并没有什么实质的作用,经过段映射的线性地址==逻辑地址。因为所有进程的段空间都一样,所以大家共享一个全局的GDT,而没有使用LDT。
接着是页映射,因为段映射什么事情都没干,所以从逻辑地址转换到物理地址的工作都由页映射来处理。在Linux中,线性地址被分组成定长的页,物理地址也被分成定长的页(4k),两者是一一对应的,便于管理和维护。每个进程有自己独立的页面目录PGD,保存在进程的mm_struct结构中。当进程切换的时候,内核将该进程的页目录物理地址放到控制寄存器CR3中,然后系统根据页目录找到相应的页表地址,然后根据相应的页表,找到最终的物理地址(这个物理地址的寻址上限也是4G,即最大支持4G的物理内存,当然有别的技术提升,这里就不谈了)。

看完这段大家可能会有个两个问题,为什么Linux不使用分段机制? 既然不使用分段机制,为什么还要保留它?
第一个问题刚才提到过,即分段机制有其缺陷,即段长不定,而且这些段要么全部换入,要么全部换出,粒度太大。定长的分页机制在内存利用,管理上都有其优势。此外,分段机制有着Intel历史遗留的性质,为了方便迁移到那些不支持分段机制的平台上,只好在段映射时少做事情。
那么为什么不能直接抛弃分段机制,只保留分页机制呢?这是因为在IA-32体系中规定段模式是不能被禁止的,反而分页模式是可选的,也就是说在Intel平台上必须要进行段映射(主要是为了MMU),Linux不能直接从逻辑地址就直接映射到物理地址。因此Linux只能使用基地址为0,大小为4GB的段来绕过这个问题,这样的段实际上是没有什么意义的(这种模式也被称为flat模式)。
 
在Linux上,访存的大致过程是这样的:
程序的逻辑地址==段映射后的线性地址---->页映射---->物理地址

经过这一系列操作,一个虚存空间的逻辑地址就变成了内存上的物理地址。通常情况下物理内存都小于进程虚存的大小(4G),即便是物理内存较大,多道程序运行也允许多个进程"同时"占用着物理内存,所以物理内存通常是不够的。需要Linux把某些暂时用不到的页面从物理内存中换出,将挪出的内存交给最需要的进程。当要重新使用那些被交换出去的页面的时候,访存指令会触发一个Page-Fault异常,在异常处理函数中把换出的页面再装回内存中,当然此时可能需要再换出另一个页面。通常被换出的内存放到磁盘的一个特殊分区中,即swap分区(在Windows上叫虚拟内存,注意和进程的虚存空间区别)。所以当你的内存不够时,可以适当的调大swap的大小,当然因为性能的原因扩展内存容量可能更有效果。

小结:
    1. IA-32中的地址转换:逻辑地址-->段映射-->线性地址-->页映射-->物理地址
    2. 分段机制和分页机制,理论上是项目独立的,既可以只使用分段,也可以是使用分页,当然也可以混合使用。
    3. Linux采用的是基于分页机制的内存管理,但是为了和Intel平台兼容,保留了段映射操作。
    4. Linux除了要参与从逻辑地址到物理地址的寻址过程,还要负责物理内存页面的换入换出工作。
    5. 从应用程序的角度,只需要考虑逻辑地址的使用就可以了,也就是好好利用自己独占的这4G虚拟内存。

在本文的开头,我说过内存访和管理是一个跨越应用程序,操作系统,硬件平台的一个复杂的过程。这次我们看了看硬件平台和操作系统做了些什么事情,下次我们将站在应用程序的角度,看看虚存是如何被使用和管理。

To Be Continued

Pthread 08/01/20
(gdb) bt #0 lv_obj_get_ext_draw_size (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_draw.c:313 #1 0x0004f42c in lv_obj_invalidate (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_pos.c:847 #2 0x00032ec0 in lv_image_set_src (obj=0x0, src=0x24f473) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/widgets/image/lv_image.c:206 #3 0x000ac70e in main_menu_event_cb (e=<optimized out>) at TpMenu.c:450 #4 0x0003c40e in lv_event_send (list=list@entry=0x3d0e14 <work_mem_int+1400824>, e=e@entry=0xbef5b2a4, preprocess=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_event.c:77 #5 0x000481ec in event_send_core (e=e@entry=0xbef5b2a4) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_event.c:367 #6 0x000482d2 in lv_obj_send_event (obj=<optimized out>, event_code=<optimized out>, param=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_event.c:67 #7 0x00017bf0 in send_event (code=LV_EVENT_CLICKED, param=0x37c0b8 <work_mem_int+1053340>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:2038 #8 0x0001842c in indev_proc_release (indev=indev@entry=0x37c0b8 <work_mem_int+1053340>, is_right=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:1634 #9 0x000186a0 in indev_pointer_proc (data=0xbef5b34c, i=0x37c0b8 <work_mem_int+1053340>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:777 #10 lv_indev_read (indev=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:273 #11 lv_indev_read (indev=0x37c0b8 <work_mem_int+1053340>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:219 #12 0x0003fa7c in lv_timer_exec (timer=0x37c1a4 <work_mem_int+1053576>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:326 #13 lv_timer_handler () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:107 #14 lv_timer_handler () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:63 #15 0x000156fe in main () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/main.c:68 (gdb) f 2 #2 0x00032ec0 in lv_image_set_src (obj=0x0, src=0x24f473) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/widgets/image/lv_image.c:206 206 lv_obj_invalidate(obj); (gdb) f 0 #0 lv_obj_get_ext_draw_size (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_draw.c:313 313 if(obj->spec_attr) return obj->spec_attr->ext_draw_size; (gdb) p obj\ ^CQuit (gdb) p obj No symbol "objp" in current context. (gdb) f 0 #0 lv_obj_get_ext_draw_size (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_draw.c:313 313 if(obj->spec_attr) return obj->spec_attr->ext_draw_size; (gdb) p obj $1 = (const lv_obj_t *) 0x0 (gdb) f 1 #1 0x0004f42c in lv_obj_invalidate (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_pos.c:847 847 int32_t ext_size = lv_obj_get_ext_draw_size(obj); (gdb) f 2 #2 0x00032ec0 in lv_image_set_src (obj=0x0, src=0x24f473) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/widgets/image/lv_image.c:206 206 lv_obj_invalidate(obj); (gdb) p obj $2 = (lv_obj_t *) 0x0 (gdb) f 3 #3 0x000ac70e in main_menu_event_cb (e=<optimized out>) at TpMenu.c:450 warning: Source file is more recent than executable. 450 else (gdb) thread apply all bt full Thread 6 (LWP 3791): #0 0xb63c0142 in epoll_wait () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #1 0xb6d8f944 in uloop_fetch_events (timeout=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/libubox-2013-01-29/uloop.c:359 n = <optimized out> nfds = <optimized out> n = <optimized out> nfds = <optimized out> cur = <optimized out> u = <optimized out> ev = <optimized out> #2 uloop_run_events (timeout=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/libubox-2013-01-29/uloop.c:359 cur = <optimized out> fd = <optimized out> cur = <optimized out> fd = <optimized out> stack_cur = <optimized out> events = <optimized out> #3 uloop_run () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/libubox-2013-01-29/uloop.c:724 tv = {tv_sec = 41159, tv_usec = 818443} #4 0x000c1d6c in nvrgui_ubus_server_start () at UbusServer.c:1935 No locals. #5 0x000c1dd4 in nvrgui_ubus_thread (arg=<optimized out>) at UbusServer.c:1973 path = <optimized out> __func__ = "nvrgui_ubus_thread" #6 0xb63f7d08 in start_thread () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #7 0xb63bec1a in clone () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. Backtrace stopped: previous frame identical to this frame (corrupt stack?) Thread 5 (LWP 3852): #0 0xb63f3644 in pthread_cond_wait () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #1 0x001a57de in async_task_queue_thread (arg=<optimized out>) at TpAsyncTaskQueue.c:709 curr = <optimized out> next = <optimized out> task = <optimized out> __func__ = "async_task_queue_thread" #2 0xb63f7d08 in start_thread () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. --Type <RET> for more, q to quit, c to continue without paging-- #3 0xb63bec1a in clone () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. Backtrace stopped: previous frame identical to this frame (corrupt stack?) Thread 4 (LWP 3795): #0 0xb63f3644 in pthread_cond_wait () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #1 0x001f97b8 in check_ipc_fw_thread (arg=<optimized out>) at CheckFw.c:370 No locals. #2 0xb63f7d08 in start_thread () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #3 0xb63bec1a in clone () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. Backtrace stopped: previous frame identical to this frame (corrupt stack?) Thread 3 (LWP 3788): #0 0xb63f3644 in pthread_cond_wait () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #1 0x00046e52 in lv_thread_sync_wait (sync=sync@entry=0x27c080 <work_mem_int+4708>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/osal/lv_pthread.c:137 No locals. #2 0x0005f6bc in render_thread_cb (ptr=0x27c060 <work_mem_int+4676>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/draw/sw/lv_draw_sw.c:482 u = 0x27c060 <work_mem_int+4676> __func__ = "render_thread_cb" #3 0x00046ca8 in generic_callback (user_data=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/osal/lv_pthread.c:174 thread = <optimized out> #4 0xb63f7d08 in start_thread () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #5 0xb63bec1a in clone () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. Backtrace stopped: previous frame identical to this frame (corrupt stack?) Thread 2 (LWP 3793): #0 0xb63f3644 in pthread_cond_wait () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #1 0x001f977a in check_nvr_fw_thread (arg=<optimized out>) at CheckFw.c:231 No locals. #2 0xb63f7d08 in start_thread () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. #3 0xb63bec1a in clone () from ../staging_dir/target-arm-openwrt-linux-uclibcgnueabihf/root-mstar/lib/libc.so.0 No symbol table info available. Backtrace stopped: previous frame identical to this frame (corrupt stack?) --Type <RET> for more, q to quit, c to continue without paging-- Thread 1 (LWP 3782): #0 lv_obj_get_ext_draw_size (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_draw.c:313 No locals. #1 0x0004f42c in lv_obj_invalidate (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_pos.c:847 obj_coords = {x1 = 2610392, y1 = 290493, x2 = -1091194812, y2 = 246799} ext_size = <optimized out> #2 0x00032ec0 in lv_image_set_src (obj=0x0, src=0x24f473) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/widgets/image/lv_image.c:206 src_type = <optimized out> img = <optimized out> __func__ = "lv_image_set_src" header = {magic = 0, cf = 0, flags = 0, w = 0, h = 0, stride = 0, reserved_2 = 0} res = <optimized out> scale = <optimized out> zoom = <optimized out> width = <optimized out> height = <optimized out> #3 0x000ac70e in main_menu_event_cb (e=<optimized out>) at TpMenu.c:450 code = <optimized out> obj = 0x3cf1b0 <work_mem_int+1393556> main_container = 0x3c9c2c <work_mem_int+1371664> container = 0x3d5598 <work_mem_int+1419132> pData = 0x3d5598 <work_mem_int+1419132> data = 0x272624 <syscfg_mainbuttonsinfo+280> i = <optimized out> #4 0x0003c40e in lv_event_send (list=list@entry=0x3d0e14 <work_mem_int+1400824>, e=e@entry=0xbef5b2a4, preprocess=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_event.c:77 is_preprocessed = <optimized out> filter = <optimized out> i = 0 dsc = 0x3d0ed4 <work_mem_int+1401016> size = 1 #5 0x000481ec in event_send_core (e=e@entry=0xbef5b2a4) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_event.c:367 __func__ = "event_send_core" indev_act = <optimized out> target = <optimized out> res = LV_RESULT_OK list = 0x3d0e14 <work_mem_int+1400824> parent = <optimized out> #6 0x000482d2 in lv_obj_send_event (obj=<optimized out>, event_code=<optimized out>, param=<optimized out>) --Type <RET> for more, q to quit, c to continue without paging-- at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_event.c:67 e = {current_target = 0x3cf1b0 <work_mem_int+1393556>, original_target = 0x3cf1b0 <work_mem_int+1393556>, code = LV_EVENT_CLICKED, user_data = 0x272624 <syscfg_mainbuttonsinfo+280>, param = 0x37c0b8 <work_mem_int+1053340>, prev = 0x0, deleted = 0 '\000', stop_processing = 0 '\000', stop_bubbling = 0 '\000'} res = <optimized out> #7 0x00017bf0 in send_event (code=LV_EVENT_CLICKED, param=0x37c0b8 <work_mem_int+1053340>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:2038 indev = 0x37c0b8 <work_mem_int+1053340> current_time = {tv_sec = 41159, tv_nsec = 828404905} #8 0x0001842c in indev_proc_release (indev=indev@entry=0x37c0b8 <work_mem_int+1053340>, is_right=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:1634 is_enabled = <optimized out> hovered_disable = false scroll_obj = 0x0 __func__ = "indev_proc_release" #9 0x000186a0 in indev_pointer_proc (data=0xbef5b34c, i=0x37c0b8 <work_mem_int+1053340>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:777 disp = <optimized out> disp = <optimized out> __func__ = "indev_pointer_proc" tmp = <optimized out> current_time = <optimized out> #10 lv_indev_read (indev=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:273 continue_reading = false data = {point = {x = 145, y = 557}, key = 0, btn_id = 0, enc_diff = 0, state = LV_INDEV_STATE_RELEASED, continue_reading = false} __func__ = "lv_indev_read" continue_reading = <optimized out> data = <optimized out> #11 lv_indev_read (indev=0x37c0b8 <work_mem_int+1053340>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:219 continue_reading = <optimized out> data = <optimized out> __func__ = "lv_indev_read" #12 0x0003fa7c in lv_timer_exec (timer=0x37c1a4 <work_mem_int+1053576>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:326 original_repeat_count = -1 exec = false exec = <optimized out> __func__ = "lv_timer_exec" original_repeat_count = <optimized out> #13 lv_timer_handler () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:107 state_p = <optimized out> handler_start = 41159828 --Type <RET> for more, q to quit, c to continue without paging-- next = 0x37c07c <work_mem_int+1053280> timer_active = 0x37c1a4 <work_mem_int+1053576> timer_head = <optimized out> time_until_next = <optimized out> idle_period_time = <optimized out> __func__ = "lv_timer_handler" #14 lv_timer_handler () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:63 state_p = 0x544384c <lv_global+116> handler_start = <optimized out> next = <optimized out> timer_active = <optimized out> timer_head = <optimized out> time_until_next = <optimized out> idle_period_time = <optimized out> __func__ = "lv_timer_handler" delay = <optimized out> #15 0x000156fe in main () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/main.c:68 ret = <optimized out> nvrgui_pid = 3052565696 __func__ = "main" (gdb) 帮我分析是哪行导致了内存踩踏
最新发布
11-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值