从tasklet运行用户空间进程

时间:2015-10-13 20:28:53

标签: c linux linux-kernel arm linux-device-driver

您好我正在尝试使用来自使用Allwinner SOC在ARM板(来自Olimex)的内核模块中创建的tasklet的call_usermodehelper_exec来运行用户空间进程。

我的代码很简单:

#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)

我尝试找到类似的问题,因为我正在学习驱动程序开发,但我发现所有问题都与问题有关,我们称之为内核破坏版本。 我使用自己的内核构建,并且我不排除可以与内核相关的内容,但是如果有人对某些主题是新的,他会确保代码没有任何应受谴责的错误。

所以任何帮助都将受到赞赏

2 个答案:

答案 0 :(得分:2)

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调用实际上是一个中断上下文,所以你不能在那里等待。也就是说,您无法阻止,因为没有要阻止的任务上下文。 (这就是&#34;调度,而原子&#34;告诉你。)

您需要使用流程上下文部分,或者您需要使用UMH_NO_WAIT而不是UMH_WAIT_PROC。例如,你可以拥有 使用来自UMH_WAIT_PROC的{​​{1}}进行了用户模式助手调用,因为您有一个任务上下文。

答案 1 :(得分:1)

Tasklet在soft-irq上下文中执行,因此无法休眠(调用schedule函数)。

来自另一方的Usermode助手可以睡眠(就像任何其他用户空间代码一样)。

这就是你收到BUG: scheduling while atomic消息的原因。