运行 来自 tasklet 的用户空间进程
Run userspace process from tasklet
你好我正在尝试运行用户空间进程使用call_usermodehelper_exec来自在带有Allwinner SOC的ARM板(来自Olimex)的内核模块中创建的tasklet。
我的代码很简单:
#include <linux/kernel.h>
#include <linux/module.h>
char my_tasklet_data[]="tasklet executed";
static int umh_test(void)
{
struct subprocess_info *sub_info;
char *argv[] = { "/usr/bin/logger", "help!", NULL };
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };
sub_info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
if (sub_info == NULL) return -ENOMEM;
return call_usermodehelper_exec(sub_info, UMH_WAIT_PROC);
}
void my_tasklet_function(unsigned long data)
{
printk(KERN_INFO "%s\n", (char *)data);
umh_test();
return;
}
DECLARE_TASKLET(my_tasklet, my_tasklet_function,
(unsigned long) &my_tasklet_data);
static int __init my_tasklet_init(void)
{
tasklet_schedule(&my_tasklet);
return 0;
}
module_init(my_tasklet_init);
static void __exit my_tasklet_cleanup(void)
{
tasklet_kill(&my_tasklet);
}
module_exit(my_tasklet_cleanup);
在执行 insmod tasklet.ko tasklet 之后调用了 /usr/bin/logger,但我也遇到了像这样的讨厌的内核错误:
[ 969.327698] tasklet executed
<3>BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102
[ 969.335769] BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102
<d>Modules linked in:[ 969.343861] Modules linked in:root@a20-olimex:~#tasklet(O) tasklet(O) disp_ump disp_ump mali_drm mali_drm cpufreq_powersave cpufreq_powersave cpufreq_stats cpufreq_stats drm drm cpufreq_userspace cpufreq_userspace cpufreq_conservative cpufreq_conservative mali mali g_ether g_ether pwm_sunxi pwm_sunxi sun4i_csi0 sun4i_csi0 videobuf_dma_contig videobuf_dma_contig videobuf_core videobuf_core gt2005 gt2005 sun4i_keyboard sun4i_keyboard ledtrig_heartbeat ledtrig_heartbeat leds_sunxi leds_sunxi led_class led_class sunxi_emac sunxi_emac sunxi_gmac sunxi_gmac sunxi_cedar_mod sunxi_cedar_mod 8192cu 8192cu ump ump lcd lcd [last unloaded: tasklet] [last unloaded: tasklet]
[<c0015058>] (unwind_backtrace+0x0/0x134) from [<c058455c>] (__schedule+0x744/0x7d0)
[ 969.410844] [<c0015058>] (unwind_backtrace+0x0/0x134) from [<c058455c>] (__schedule+0x744/0x7d0)
[<c058455c>] (__schedule+0x744/0x7d0) from [<c0582a20>] (schedule_timeout+0x1b8/0x220)
[ 969.427299] [<c058455c>] (__schedule+0x744/0x7d0) from [<c0582a20>] (schedule_timeout+0x1b8/0x220)
[<c0582a20>] (schedule_timeout+0x1b8/0x220) from [<c0583c04>] (wait_for_common+0xe4/0x138)
[ 969.444267] [<c0582a20>] (schedule_timeout+0x1b8/0x220) from [<c0583c04>] (wait_for_common+0xe4/0x138)
[<c0583c04>] (wait_for_common+0xe4/0x138) from [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154)
[ 969.462267] [<c0583c04>] (wait_for_common+0xe4/0x138) from [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154)
[<c0049dc0>] (call_usermodehelper_exec+0x140/0x154) from [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet])
[ 969.482096] [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154) from [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet])
[<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet]) from [<c003c800>] (tasklet_action+0x98/0x134)
[ 969.502110] [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet]) from [<c003c800>] (tasklet_action+0x98/0x134)
[<c003c800>] (tasklet_action+0x98/0x134) from [<c003c9d4>] (__do_softirq+0xd4/0x168)
[ 969.519768] [<c003c800>] (tasklet_action+0x98/0x134) from [<c003c9d4>] (__do_softirq+0xd4/0x168)
[<c003c9d4>] (__do_softirq+0xd4/0x168) from [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc)
[ 969.535943] [<c003c9d4>] (__do_softirq+0xd4/0x168) from [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc)
[<c003cb58>] (run_ksoftirqd+0xf0/0x1bc) from [<c00513a4>] (kthread+0x90/0x94)
[ 969.551513] [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc) from [<c00513a4>] (kthread+0x90/0x94)
[<c00513a4>] (kthread+0x90/0x94) from [<c000f4b8>] (kernel_thread_exit+0x0/0x8)
[ 969.566739] [<c00513a4>] (kthread+0x90/0x94) from [<c000f4b8>] (kernel_thread_exit+0x0/0x8)
我尝试寻找类似的问题,因为我正在学习驱动程序开发,但我发现的只是与以下问题相关的问题,我们称之为内核损坏的构建。
我使用自己构建的内核,我不排除可能与内核相关,但如果某人是某个主题的新手,他会确保代码没有任何应受谴责的错误。
因此,我们将不胜感激
Tasklet 在软中断上下文中执行,因此无法休眠(调用 schedule
函数)。
另一方面,用户模式助手可以休眠(就像任何其他用户空间代码一样)。
这就是您收到 BUG: scheduling while atomic
消息的原因。
call_usermodehelper_exec
的评论部分说:
* @wait: wait for the application to finish and return status.
* when UMH_NO_WAIT don't wait at all, but you get no useful error back
* when the program couldn't be exec'ed. This makes it safe to call
* from interrupt context.
从 tasklet 调用实际上是一个中断上下文,因此您不能在那里等待。也就是说,您不能阻止,因为没有可用于阻止的任务上下文。 (这就是 "scheduling while atomic" 告诉你的。)
您要么需要使用流程上下文部分,要么需要使用 UMH_NO_WAIT
而不是 UMH_WAIT_PROC
。例如,你可以有
从 my_tasklet_init
使用 UMH_WAIT_PROC
调用用户模式助手,因为那里有一个任务上下文。
你好我正在尝试运行用户空间进程使用call_usermodehelper_exec来自在带有Allwinner SOC的ARM板(来自Olimex)的内核模块中创建的tasklet。
我的代码很简单:
#include <linux/kernel.h>
#include <linux/module.h>
char my_tasklet_data[]="tasklet executed";
static int umh_test(void)
{
struct subprocess_info *sub_info;
char *argv[] = { "/usr/bin/logger", "help!", NULL };
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };
sub_info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
if (sub_info == NULL) return -ENOMEM;
return call_usermodehelper_exec(sub_info, UMH_WAIT_PROC);
}
void my_tasklet_function(unsigned long data)
{
printk(KERN_INFO "%s\n", (char *)data);
umh_test();
return;
}
DECLARE_TASKLET(my_tasklet, my_tasklet_function,
(unsigned long) &my_tasklet_data);
static int __init my_tasklet_init(void)
{
tasklet_schedule(&my_tasklet);
return 0;
}
module_init(my_tasklet_init);
static void __exit my_tasklet_cleanup(void)
{
tasklet_kill(&my_tasklet);
}
module_exit(my_tasklet_cleanup);
在执行 insmod tasklet.ko tasklet 之后调用了 /usr/bin/logger,但我也遇到了像这样的讨厌的内核错误:
[ 969.327698] tasklet executed
<3>BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102
[ 969.335769] BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102
<d>Modules linked in:[ 969.343861] Modules linked in:root@a20-olimex:~#tasklet(O) tasklet(O) disp_ump disp_ump mali_drm mali_drm cpufreq_powersave cpufreq_powersave cpufreq_stats cpufreq_stats drm drm cpufreq_userspace cpufreq_userspace cpufreq_conservative cpufreq_conservative mali mali g_ether g_ether pwm_sunxi pwm_sunxi sun4i_csi0 sun4i_csi0 videobuf_dma_contig videobuf_dma_contig videobuf_core videobuf_core gt2005 gt2005 sun4i_keyboard sun4i_keyboard ledtrig_heartbeat ledtrig_heartbeat leds_sunxi leds_sunxi led_class led_class sunxi_emac sunxi_emac sunxi_gmac sunxi_gmac sunxi_cedar_mod sunxi_cedar_mod 8192cu 8192cu ump ump lcd lcd [last unloaded: tasklet] [last unloaded: tasklet]
[<c0015058>] (unwind_backtrace+0x0/0x134) from [<c058455c>] (__schedule+0x744/0x7d0)
[ 969.410844] [<c0015058>] (unwind_backtrace+0x0/0x134) from [<c058455c>] (__schedule+0x744/0x7d0)
[<c058455c>] (__schedule+0x744/0x7d0) from [<c0582a20>] (schedule_timeout+0x1b8/0x220)
[ 969.427299] [<c058455c>] (__schedule+0x744/0x7d0) from [<c0582a20>] (schedule_timeout+0x1b8/0x220)
[<c0582a20>] (schedule_timeout+0x1b8/0x220) from [<c0583c04>] (wait_for_common+0xe4/0x138)
[ 969.444267] [<c0582a20>] (schedule_timeout+0x1b8/0x220) from [<c0583c04>] (wait_for_common+0xe4/0x138)
[<c0583c04>] (wait_for_common+0xe4/0x138) from [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154)
[ 969.462267] [<c0583c04>] (wait_for_common+0xe4/0x138) from [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154)
[<c0049dc0>] (call_usermodehelper_exec+0x140/0x154) from [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet])
[ 969.482096] [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154) from [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet])
[<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet]) from [<c003c800>] (tasklet_action+0x98/0x134)
[ 969.502110] [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet]) from [<c003c800>] (tasklet_action+0x98/0x134)
[<c003c800>] (tasklet_action+0x98/0x134) from [<c003c9d4>] (__do_softirq+0xd4/0x168)
[ 969.519768] [<c003c800>] (tasklet_action+0x98/0x134) from [<c003c9d4>] (__do_softirq+0xd4/0x168)
[<c003c9d4>] (__do_softirq+0xd4/0x168) from [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc)
[ 969.535943] [<c003c9d4>] (__do_softirq+0xd4/0x168) from [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc)
[<c003cb58>] (run_ksoftirqd+0xf0/0x1bc) from [<c00513a4>] (kthread+0x90/0x94)
[ 969.551513] [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc) from [<c00513a4>] (kthread+0x90/0x94)
[<c00513a4>] (kthread+0x90/0x94) from [<c000f4b8>] (kernel_thread_exit+0x0/0x8)
[ 969.566739] [<c00513a4>] (kthread+0x90/0x94) from [<c000f4b8>] (kernel_thread_exit+0x0/0x8)
我尝试寻找类似的问题,因为我正在学习驱动程序开发,但我发现的只是与以下问题相关的问题,我们称之为内核损坏的构建。 我使用自己构建的内核,我不排除可能与内核相关,但如果某人是某个主题的新手,他会确保代码没有任何应受谴责的错误。
因此,我们将不胜感激
Tasklet 在软中断上下文中执行,因此无法休眠(调用 schedule
函数)。
另一方面,用户模式助手可以休眠(就像任何其他用户空间代码一样)。
这就是您收到 BUG: scheduling while atomic
消息的原因。
call_usermodehelper_exec
的评论部分说:
* @wait: wait for the application to finish and return status.
* when UMH_NO_WAIT don't wait at all, but you get no useful error back
* when the program couldn't be exec'ed. This makes it safe to call
* from interrupt context.
从 tasklet 调用实际上是一个中断上下文,因此您不能在那里等待。也就是说,您不能阻止,因为没有可用于阻止的任务上下文。 (这就是 "scheduling while atomic" 告诉你的。)
您要么需要使用流程上下文部分,要么需要使用 UMH_NO_WAIT
而不是 UMH_WAIT_PROC
。例如,你可以有
从 my_tasklet_init
使用 UMH_WAIT_PROC
调用用户模式助手,因为那里有一个任务上下文。