简体   繁体   English

无法从Linux中的设备驱动程序调用Fork()

[英]Fork() cannot be called from a Device Driver in linux

So, I'm writing this driver wich recieves a "command" via "write" and it is supposed to call fork and let the child finish the job while the parent dies. 因此,我正在编写此驱动程序,该驱动程序通过“写入”接收到一个“命令”,并且应该调用fork并让孩子在父母去世时完成工作。

When I compile it the output is this. 当我编译它的输出是这个。

victor@victor-desktop:~/Área de Trabalho/mc504-linux/linux-3.17.2$ make -j 5 ARCH=i386
CHK     include/config/kernel.release
CHK     include/generated/uapi/linux/version.h
CHK     include/generated/utsrelease.h
CALL    scripts/checksyscalls.sh
CHK     include/generated/compile.h
CC [M]  drivers/ofd/ofcd-lastchar.o
drivers/ofd/ofcd-lastchar.c: In function ‘my_read’:
drivers/ofd/ofcd-lastchar.c:36:5: error: implicit declaration of function ‘fork’ [-Werror=implicit-function-declaration
 child_pid = fork();
 ^
cc1: some warnings being treated as errors
scripts/Makefile.build:263: recipe for target 'drivers/ofd/ofcd-lastchar.o' failed
make[2]: *** [drivers/ofd/ofcd-lastchar.o] Error 1
scripts/Makefile.build:404: recipe for target 'drivers/ofd' failed
make[1]: *** [drivers/ofd] Error 2
Makefile:929: recipe for target 'drivers' failed
make: *** [drivers] Error 2

I'm using a linux downloaded from here . 我正在使用从此处下载的linux。

And the driver is this. 而司机就是这个。 It only has a fork() call. 它只有一个fork()调用。

#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
#include <linux/sched.h>

static dev_t first; // Global variable for the first device number
static struct cdev c_dev; // Global variable for the character device structure
static struct class *cl; // Global variable for the device class

static char c;

static int my_open(struct inode *i, struct file *f)
{
  /*
  Abrir devera alocar um pedaço da memoria e salvar 
  */
  printk(KERN_INFO "Driver: open()\n");
  return 0;
}
static int my_close(struct inode *i, struct file *f)
{
  printk(KERN_INFO "Driver: close()\n");
  return 0;
}

static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off)
{
    pid_t child_pid;
    child_pid = fork();
    if(child_pid == 0)
      printk(KERN_INFO "child: read()\n");
    else
      printk(KERN_INFO "father: read()\n");
    if (copy_to_user(buf, &c, 1) != 0)
        return -EFAULT;
    else
        return 1;
}
static ssize_t my_write(struct file *f, const char __user *buf, size_t len, loff_t *off)
{
    printk(KERN_INFO "Driver: write()\n");
    if (copy_from_user(&c, buf + len - 1, 1) != 0)
        return -EFAULT;
    else
        return len;
};

static struct file_operations pugs_fops =
  {
      .owner = THIS_MODULE,
      .open = my_open,
      .release = my_close,
      .read = my_read,
      .write = my_write
  };

static int __init ofcd_init(void) /* Constructor */
{
  printk(KERN_INFO "Namaskar: ofcd-lastchar registered");
  if (alloc_chrdev_region(&first, 0, 1, "ofcd-lastchar") < 0)
    {
      return -1;
    }
  if ((cl = class_create(THIS_MODULE, "chardrv")) == NULL)
    {
      unregister_chrdev_region(first, 1);
      return -1;
    }
  if (device_create(cl, NULL, first, NULL, "ofcd-lastchar") == NULL)
    {
      class_destroy(cl);
      unregister_chrdev_region(first, 1);
      return -1;
    }
  cdev_init(&c_dev, &pugs_fops);
  if (cdev_add(&c_dev, first, 1) == -1)
    {
      device_destroy(cl, first);
      class_destroy(cl);
      unregister_chrdev_region(first, 1);
      return -1;
    }
  return 0;
}

static void __exit ofcd_exit(void) /* Destructor */
{
  cdev_del(&c_dev);
  device_destroy(cl, first);
  class_destroy(cl);
  unregister_chrdev_region(first, 1);
  printk(KERN_INFO "Alvida: ofcd-lastchar unregistered");
}

module_init(ofcd_init);
module_exit(ofcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Character Driver");

The big question is: Can fork(); 最大的问题是:是否可以fork(); be called from a Device Driver? 从设备驱动程序调用?

You cannot use syscalls(2) inside the Linux kernel (because syscalls are the interface from user-land applications to kernel ), and you really should not start a process inside a driver , since with a few painful exceptions (like /sbin/init of pid 1, or maybe in some particular cases /sbin/hotplug etc...) every process is started by another process calling fork(2) (or perhaps clone(2) or vfork(2) ...). 您不能在Linux内核中使用syscalls(2) (因为syscalls是从用户界面应用程序到内核的接口),并且您实际上不应该在驱动程序内部启动进程,因为有一些痛苦的异常(例如/sbin/init pid 1,或者在某些特定情况下/sbin/hotplug等),每个进程都是由另一个进程调用fork(2) (或者也许clone(2)vfork(2) ...)启动的。 Your kernel module becomes part of the kernel when loaded (eg with insmod(8) ...); 您的内核模块在加载时成为内核的一部分(例如,使用insmod(8) ...); however, kernel threads add complexity to the picture. 但是, 内核线程增加了画面的复杂性。

Maybe you should consider FUSE . 也许您应该考虑FUSE

I recommend learning much more about Linux user-land programming (eg read Advanced Linux Programming ) before daring coding some kernel module. 我建议在不敢编码某些内核模块之前,学习更多有关Linux用户界面编程的知识(例如,阅读Advanced Linux Programming )。

You might read about continuations & CPS & fibers . 您可能会阅读有关延续性CPS纤维的信息 It could suggest you a way of thinking your driver code differently. 它可能会建议您以不同的方式考虑驱动程序代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM