深做网站公司,wordpress 插件 朋友圈,廊坊模板建站代理,2022楼市最新消息这是一个老生常谈的问题。我们先简单说下什么是中断「因为最近在群里看到有人竟然不懂什么是中断」。中断是计算机里面非常核心的东西#xff0c;我们可以跑OS#xff0c;可以多任务运行都因为中断的存在。假设你是一个CPU#xff0c;你正在睡觉。你突然觉得肚子疼#xff… 这是一个老生常谈的问题。我们先简单说下什么是中断「因为最近在群里看到有人竟然不懂什么是中断」。中断是计算机里面非常核心的东西我们可以跑OS可以多任务运行都因为中断的存在。假设你是一个CPU你正在睡觉。你突然觉得肚子疼「这个事情就是一个中断你睡觉的事情」然后你就去上厕所了。然后你又回到床上睡觉。你突然又觉得肚子饿了「这个事情也是一个中断你睡觉的事情」然后你就去吃了个汉堡。中断可以认为是突发的事情并且时间不是特别长如果时间非常久那就不能叫中断了就叫主业了。CPU怎么用中断做到多任务运行呢CPU不是普通的人CPU比普通的人快得多得多。就拿我手上最差的新唐单片机举例子他的主频是24M那执行一条指令周期的时间就是1/24000000 41.6 纳秒
假设你现在有两个事情要做玩王者荣耀和扫地你在第一个时钟周期拿着手机玩王者荣耀第二个时钟周期扫地第三个时钟周期玩王者荣耀第四个时钟周期扫地……这样你会发现CPU是一个闪电侠可能比闪电侠还要快根据这个方法可以裂变出很多很多个人做很多很多件事情。Linux 内核中断上文为什么不能休眠呢现在的Linux 内核中断是不能嵌套的所以我们就只讨论单中断的问题。进中断的第一件事情就是关中断这个是关所有中断。然后就在中断里面干事情了具体做什么事情我也不知道。做完事情然后就开中断去做其他事情了。如果休眠会引起什么呢比如这样的代码static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc)
{TPD_DEBUG_PRINT_INT;tpd_flag 1;/* enter EINT handler disable INT, make sure INT is disable when handle touch event including top/bottom half *//* use _nosync to avoid deadlock */spin_lock(irq_lock);if (tpd_irq_flag) {tpd_irq_flag 0;disable_irq_nosync(tpd_touch_irq);}spin_unlock(irq_lock);ssleep(1);//系统会死掉wake_up_interruptible(waiter);return IRQ_HANDLED;
}
这个代码的问题在ssleep(1)上ssleep(1)是OS里面的休眠函数这个函数会让任务休眠休眠的意思就是让这个任务睡觉不执行CPU去执行其他的任务。因为CPU是按时间片执行的等下一次调度到这个中断的时候就有可能再获取一次spin_lock自旋锁两次获取锁的操作肯定就引起系统挂壁了。具体的可以去看看ssleep的代码/*** msleep - sleep safely even with waitqueue interruptions* msecs: Time in milliseconds to sleep for*/
void msleep(unsigned int msecs)
{unsigned long timeout msecs_to_jiffies(msecs) 1;while (timeout)timeout schedule_timeout_uninterruptible(timeout);
}EXPORT_SYMBOL(msleep);
系统宕机日志[ 1.564767] 3.(3)[139:kworker/u8:2]GTP-INF[tpd_irq_registration:484] Device Tree Tpd_irq_registration!
[ 1.566520] 3.(3)[139:kworker/u8:2]gpiod_set_debounce: invalid GPIO
[ 1.567319] 3.(3)[139:kworker/u8:2]GTP-INF[tpd_irq_registration:495] Device gt1x_int_type 1!
[ 1.568484] 0-(0)[0:swapper/0]BUG: scheduling while atomic: swapper/0/0/0x00010002
[ 1.568493] 0.(3)[139:kworker/u8:2]GTP-INF[tpd_irq_registration:514] irq:119, debounce:0-0:
[ 1.570534] Modules linked in:
[ 1.570912] 0-(0)[0:swapper/0]CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.146 #41
[ 1.571879] 0-(0)[0:swapper/0]Hardware name: Generic DT based system
[ 1.572689] Backtrace:
[ 1.572989] 0-(0)[0:swapper/0][c010d5d4] (dump_backtrace) from [c010d7fc] (show_stack0x18/0x1c)
[ 1.574143] r6:60000193 r5:c1136bc8 r4:00000000 r3:dc8ba692
[ 1.574841] 0-(0)[0:swapper/0][c010d7e4] (show_stack) from [c041b4c4] (dump_stack0x94/0xa8)
[ 1.575950] 0-(0)[0:swapper/0][c041b430] (dump_stack) from [c0155350] (__schedule_bug0x58/0x6c)
[ 1.577104] r6:c1101ce8 r5:c1085b40 r4:00000000 r3:60000193
[ 1.577802] 0-(0)[0:swapper/0][c01552f8] (__schedule_bug) from [c0b6dc88] (__schedule0x59c/0x808)
[ 1.578978] r4:c110bcf8 r3:00010002
[ 1.579418] 0-(0)[0:swapper/0][c0b6d6ec] (__schedule) from [c0b6df48] (schedule0x54/0xc4)
[ 1.580507] r10:00000000 r9:c1102100 r8:dfedfb80 r7:c1103948
[ 1.581216] 0-(0)[0:swapper/0][c0b6def4] (schedule) from [c0b712c4] (schedule_timeout0x148/0x264)
[ 1.582391] r4:fffea370 r3:c1100000
[ 1.582831] 0-(0)[0:swapper/0][c0b7117c] (schedule_timeout) from [c01ad8f8] (msleep0x34/0x40)
[ 1.583964] r10:c1100000 r9:00000000 r8:00000000 r7:00000077
[ 1.584673] 0-(0)[0:swapper/0][c01ad8c4] (msleep) from [c081e0d0] (tpd_eint_interrupt_handler0x2c/0xd8)
[ 1.585913] r5:ced00000 r4:cec8d540
[ 1.586353] 0-(0)[0:swapper/0][c081e0a4] (tpd_eint_interrupt_handler) from [c0199684] (handle_irq_event_percpu0x6c/0x268)
[ 1.587787] r5:d0344ae0 r4:cec8d540
[ 1.588227] 0-(0)[0:swapper/0][c0199618] (handle_irq_event_percpu) from [c01998c0] (handle_irq_event0x40/0x64)
[ 1.589542] r10:c0c487cc r9:00000077 r8:00000000 r7:00000000
[ 1.590251] 0-(0)[0:swapper/0][c0199880] (handle_irq_event) from [c019d388] (handle_level_irq0xb4/0x16c)
[ 1.591502] r6:d0344a90 r5:d0344ae0 r4:d0344a80 r3:00020002
[ 1.592201] 0-(0)[0:swapper/0][c019d2d4] (handle_level_irq) from [c0198b64] (generic_handle_irq0x2c/0x3c)
[ 1.593462] r6:d030e6d0 r5:02000000 r4:00000019 r3:c019d2d4
[ 1.594161] 0-(0)[0:swapper/0][c0198b38] (generic_handle_irq) from [c045d7e4] (mtk_eint_irq_handler0x288/0x36c)
[ 1.595486] 0-(0)[0:swapper/0][c045d55c] (mtk_eint_irq_handler) from [c0198b64] (generic_handle_irq0x2c/0x3c)
[ 1.596790] r10:00000001 r9:00000000 r8:00010001 r7:00000000
[ 1.597499] 0-(0)[0:swapper/0][c0198b38] (generic_handle_irq) from [c0198e7c] (__handle_domain_irq0xc0/0x25c)
[ 1.598802] 0-(0)[0:swapper/0][c0198dbc] (__handle_domain_irq) from [c01015ec] (gic_handle_irq0x50/0x94)
[ 1.600053] r9:e1003000 r8:e1002000 r7:c1101eb0 r6:e100200c
[ 1.600752] 0-(0)[0:swapper/0][c010159c] (gic_handle_irq) from [c010e314] (__irq_svc0x54/0x90)
[ 1.601893] 0-(0)[0:swapper/0]Exception stack(0xc1101eb0 to 0xc1101ef8)
[ 1.602736] 0-(0)[0:swapper/0]1ea0: 00000000 ffffffff 1ee35000 00000000
[ 1.603965] 0-(0)[0:swapper/0]1ec0: c11ac9b4 cfbdf800 5cc9dbdf 00000000 5ccecf4c 00000000 00000001 c1101f44
[ 1.605192] 0-(0)[0:swapper/0]1ee0: c1101f00 c1101f00 c08a2380 c08a2390 60000013 ffffffff
[ 1.606224] r9:00000000 r8:5ccecf4c r7:c1101ee4 r6:ffffffff
[ 1.606922] 0-(0)[0:swapper/0][c08a2220] (cpuidle_enter_state) from [c08a2670] (cpuidle_enter0x1c/0x20)
[ 1.608162] r10:c1103a1c r9:c1187308 r8:cfbdf800 r7:c11ac9b4
[ 1.608872] 0-(0)[0:swapper/0][c08a2654] (cpuidle_enter) from [c0183334] (cpu_startup_entry0x1e0/0x3d8)
[ 1.610110] 0-(0)[0:swapper/0][c0183154] (cpu_startup_entry) from [c0b6ac18] (rest_init0x90/0x94)
[ 1.611285] r7:ffffffff
[ 1.611596] 0-(0)[0:swapper/0][c0b6ab88] (rest_init) from [c1000e44] (start_kernel0x418/0x468)
[ 1.612739] r4:c11b1040 r3:dc8ba692
[ 1.613179] 0-(0)[0:swapper/0]Backtrace aborted due to bad pc c1000a30
[ 1.614040] 0-(0)[0:swapper/0]------------[ cut here ]------------
[ 1.614816] 0-(0)[0:swapper/0]Kernel BUG at c0155360 [verbose debug info unavailable]
[ 1.615807] 0-(0)[0:swapper/0]Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
[ 1.616746] 0-(0)[0:swapper/0][LY]rtc_mark_aee_kernel_panic!!!
[ 1.617551] disable aee kernel api
[ 1.617935] 0-(0)[0:swapper/0]Kernel Offset: disabled
[ 1.618603] Modules linked in:
Linux 内核中断函数能不能执行malloc函数这个是之前已经发过的文章可以在中断服务程序执行malloc吗内核里面分配内存的函数是kmalloc ,其他不废话我直接测试了下面的代码static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc)
{char *rbuff NULL;rbuff kmalloc(1024, GFP_KERNEL);TPD_DEBUG_PRINT_INT;tpd_flag 1;/* enter EINT handler disable INT, make sure INT is disable when handle touch event including top/bottom half *//* use _nosync to avoid deadlock */spin_lock(irq_lock);if (tpd_irq_flag) {tpd_irq_flag 0;disable_irq_nosync(tpd_touch_irq);}spin_unlock(irq_lock);ssleep(1);//系统会死掉wake_up_interruptible(waiter);kfree(rbuff);return IRQ_HANDLED;
}
系统是没有挂掉的然后去看看kmalloc的实现。/*** kmalloc - allocate memory* size: how many bytes of memory are required.* flags: the type of memory to allocate.** kmalloc is the normal method of allocating memory* for objects smaller than page size in the kernel.** The flags argument may be one of:** %GFP_USER - Allocate memory on behalf of user. May sleep.** %GFP_KERNEL - Allocate normal kernel ram. May sleep.** %GFP_ATOMIC - Allocation will not sleep. May use emergency pools.* For example, use this inside interrupt handlers.** %GFP_HIGHUSER - Allocate pages from high memory.** %GFP_NOIO - Do not do any I/O at all while trying to get memory.** %GFP_NOFS - Do not make any fs calls while trying to get memory.** %GFP_NOWAIT - Allocation will not sleep.** %__GFP_THISNODE - Allocate node-local memory only.** %GFP_DMA - Allocation suitable for DMA.* Should only be used for kmalloc() caches. Otherwise, use a* slab created with SLAB_DMA.** Also it is possible to set different flags by ORing* in one or more of the following additional flags:** %__GFP_COLD - Request cache-cold pages instead of* trying to return cache-warm pages.** %__GFP_HIGH - This allocation has high priority and may use emergency pools.** %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail* (think twice before using).** %__GFP_NORETRY - If memory is not immediately available,* then give up at once.** %__GFP_NOWARN - If allocation fails, dont issue any warnings.** %__GFP_REPEAT - If allocation fails initially, try once more before failing.** There are other flags available as well, but these are not intended* for general use, and so are not documented here. For a full list of* potential flags, always refer to linux/gfp.h.*/
static __always_inline void *kmalloc(size_t size, gfp_t flags)
{if (__builtin_constant_p(size)) {if (size KMALLOC_MAX_CACHE_SIZE)return kmalloc_large(size, flags);
#ifndef CONFIG_SLOBif (!(flags GFP_DMA)) {int index kmalloc_index(size);if (!index)return ZERO_SIZE_PTR;return kmem_cache_alloc_trace(kmalloc_caches[index],flags, size);}
#endif}return __kmalloc(size, flags);
}
代码里面没有看到引起调度的代码但是注释里面有说会引起休眠。这个函数跟微信微信公众号留言提到的gfp一致。推荐阅读专辑|Linux文章汇总专辑|程序人生专辑|C语言我的知识小密圈关注公众号后台回复「1024」获取学习资料网盘链接。欢迎点赞关注转发在看您的每一次鼓励我都将铭记于心~