无法从 Linux 中的设备 Driver 调用 Fork()
Fork() cannot be called from a Device Driver in Linux
所以,我正在编写这个 driver,它通过“写入”接收“命令”,它应该调用 fork 并让 child 完成工作,而 parent 死了。
当我编译它时,输出是这样的。
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
我正在使用从 here 下载的 Linux。
而 driver 就是这个。它只有一个 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");
最大的问题是:可以从设备 Driver 调用 fork();
吗?
你不能使用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)...). Your kernel module becomes part of the kernel when loaded (e.g. with insmod(8)...); however, kernel threads增加图片的复杂性。
也许你应该考虑 FUSE。
我建议在大胆编写一些内核模块之前,多学习 Linux 用户级编程(例如阅读 Advanced Linux Programming)。
您可能会读到 continuations & CPS & fibers。它可以建议您以不同的方式思考您的驱动程序代码。
所以,我正在编写这个 driver,它通过“写入”接收“命令”,它应该调用 fork 并让 child 完成工作,而 parent 死了。
当我编译它时,输出是这样的。
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
我正在使用从 here 下载的 Linux。
而 driver 就是这个。它只有一个 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");
最大的问题是:可以从设备 Driver 调用 fork();
吗?
你不能使用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)...). Your kernel module becomes part of the kernel when loaded (e.g. with insmod(8)...); however, kernel threads增加图片的复杂性。
也许你应该考虑 FUSE。
我建议在大胆编写一些内核模块之前,多学习 Linux 用户级编程(例如阅读 Advanced Linux Programming)。
您可能会读到 continuations & CPS & fibers。它可以建议您以不同的方式思考您的驱动程序代码。