我通过查看示例制作了简单的字符驱动程序。但是,我没有看到/ dev / simple中的驱动程序简单。为什么不在那里创建?我也没有看到任何错误问题。我错过了什么,有什么问题吗?
#include <linux/init.h>
#include <linux/module.h> /** needed by all modules **/
#include <linux/kernel.h> /** This is for KERN_ALERT **/
#include <linux/fs.h>
#include <linux/cdev.h>
/** for putuser **/
#include <asm/uaccess.h>
MODULE_LICENSE("SJ BSD/GPL");
static struct cdev SimpleDevs[2];
static int simple_major = 0;
static ssize_t sj_read(struct file *filp,
char *buffer, /* The buffer to fill with data */
size_t length, /* The length of the buffer */
loff_t *offset);
static int sj_open(struct inode *inode, struct file *file);
static struct file_operations fops = {
.read = sj_read,
//.write = sj_write,
.open = sj_open,
//.release = sj_release
};
static ssize_t sj_read(struct file *filp,
char *buffer, /* The buffer to fill with data */
size_t length, /* The length of the buffer */
loff_t *offset) /* Our offset in the file */
{
char msg[1024] = "Hello SJ_read";
copy_to_user( buffer, msg, sizeof(msg) );
return sizeof(msg);
}
static void simple_setup_cdev(struct cdev *dev, int minor,
struct file_operations *fops)
{
int err, devno = MKDEV(simple_major, minor);
dev = cdev_alloc();
cdev_init(dev, fops);
dev->owner = THIS_MODULE;
dev->ops = fops;
err = cdev_add (dev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk (KERN_NOTICE "Error %d adding simple%d", err, minor);
}
static int sjDevInit(void)
{
int result;
dev_t dev;
printk("Device Init now..");
/** int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name); **/
/** dev -> The dev_t variable type,which will get the major number that the kernel allocates. **/
/**The same name will appear in /proc/devices. **/
result = alloc_chrdev_region(&dev, 0, 1, "simple");
if( result < 0 )
{
printk("Error in allocating device");
return -1;
}
// printk("simple_major ..");
simple_major = MAJOR(dev);
printk("simple_major number is %d ..\r\n",simple_major );
/* Now set up two cdevs. */
simple_setup_cdev(SimpleDevs, 0, &fops);
simple_setup_cdev(SimpleDevs + 1, 1, &fops);
return 0;
}
static void sjDevRel(void)
{
printk("Releasing Simple Devs\r\n");
cdev_del(SimpleDevs);
}
static int sj_open(struct inode *inode, struct file *file)
{
printk("Kernel..Sj_open ..I am opened\r\n");
return 0;
}
module_init(sjDevInit);
module_exit(sjDevRel);
答案 0 :(得分:1)
节点设备可以在收到mknod
消息时手动创建(通过直接调用udevd
)或uevent
守护程序。该消息由“操作”字段(ADD
,REMOVE
等)和一组键{/值对组成,udevd
可以查看以决定调用哪个规则。
要发出事件,您需要获取kobject((struct cdev *)->kobj
)的句柄。完全创建设备后,您需要执行以下操作:
err = cdev_add (dev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk (KERN_NOTICE "Error %d adding simple%d", err, minor);
kobject_uevent(&dev->kobj, KOBJ_ADD);
在移除设备之前,您需要执行相反的操作:
kobject_uevent(&SimpleDevs[0]->kobj, KOBJ_REMOVE);
printk("Releasing Simple Devs\r\n");
cdev_del(SimpleDevs[0]);
(顺便说一句,你的代码有一个主要的指针处理错误,涉及你SimpleDevs
变量的定义和用法,你应该对其进行整理和修复。
此时您可以使用udevadm monitor
命令进行实验,看看您是否从驱动程序获取消息并使用任何udev教程编写适当的规则(例如:https://wiki.debian.org/udev)
如果您想为您的uevent消息添加更多信息,可以尝试使用更详细的kobject_uevent_env()
API。这通常看起来像这样:
char event[] = "DISK_RO=1";
char *envp[] = { event, NULL };
if (!ro)
event[8] = '0';
kobject_uevent_env(&disk_to_dev(gd)->kobj, KOBJ_CHANGE, envp);
http://code.metager.de/source/xref/linux/stable/block/genhd.c#1320
如果你想要更高级的消息,通常的方法是保留一个适当大小的固定内存块,并在将其传递给uevent之前用snprintf
填充它。