Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 何时调用parport_driver.attach()?_Linux_Linux Kernel_Linux Device Driver - Fatal编程技术网

Linux 何时调用parport_driver.attach()?

Linux 何时调用parport_driver.attach()?,linux,linux-kernel,linux-device-driver,Linux,Linux Kernel,Linux Device Driver,我正在运行《基本Linux设备驱动程序》一书中的示例“并行LED板驱动程序(LED.c)”。一个问题是永远不会调用led_attach() 这个链接谈论相同的话题 您首先要注册一个名为“led”的class_设备(class_device_create)。之后,内核知道有一个名为“led”的设备。当您注册led_驱动程序时,它的名称也是“led”,因此内核将两者匹配,并调用led_驱动程序结构的附加函数 我确实使用“led”作为设备名和led_驱动程序名,模块名也为led.ko。但是,不会以任何

我正在运行《基本Linux设备驱动程序》一书中的示例“并行LED板驱动程序(LED.c)”。一个问题是永远不会调用led_attach()

这个链接谈论相同的话题

您首先要注册一个名为“led”的class_设备(class_device_create)。之后,内核知道有一个名为“led”的设备。当您注册led_驱动程序时,它的名称也是“led”,因此内核将两者匹配,并调用led_驱动程序结构的附加函数

我确实使用“led”作为设备名和led_驱动程序名,模块名也为led.ko。但是,不会以任何方式调用led_attach()

这是我的密码:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>

#include <linux/parport.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h>
#include <linux/sched.h>

#define DEVICE_NAME "led"

static dev_t dev_number;        /* Allotted device number */
static struct class *led_class; /* Class to which this device belongs */
struct cdev led_cdev;           /* Associated cdev */
struct pardevice *pdev;         /* Parallel port device */

/* LED open */
int led_open(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "(pid:%d, cmd:%s)led_open(major: %d, minor: %d)\n",
           current->pid, current->comm, imajor(inode), iminor(inode));
    return 0;
}

/* Write to the LED */
ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
    printk(KERN_INFO "(pid:%d, cmd:%s)led_write(count: %d, *ppos: %lld)\n",
           current->pid, current->comm, count, *ppos);
    return count;
}

/* Release the device */
int led_release(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "(pid:%d, cmd:%s)led_release()\n", current->pid, current->comm);
    return 0;
}

/* File Operations */
static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .write = led_write,
    .release = led_release,
};

static int led_preempt(void *handle)
{
    printk(KERN_INFO "(pid:%d, cmd:%s)led_preempt()\n", current->pid, current->comm);
    return 1;
}

/* Parport attach method */
static void led_attach(struct parport *port)
{
    printk(KERN_INFO "(pid:%d, cmd:%s)led_attach()\n", current->pid, current->comm);

    /* Register the parallel LED device with parport */
    pdev = parport_register_device(port, DEVICE_NAME,
                                   led_preempt, NULL,
                                   NULL, 0, NULL);
    if (pdev == NULL) printk("Bad register\n");
}

/* Parport detach method */
static void led_detach(struct parport *port)
{
    printk(KERN_INFO "(pid:%d, cmd:%s)led_detach() Port Detached\n", current->pid, current->comm);
    /* Do nothing */
    parport_unregister_device(pdev);
}

/* Parport driver operations */
static struct parport_driver led_driver = {
    .name = DEVICE_NAME,
    .attach = led_attach,
    .detach = led_detach,
};


/* Driver Initialization */
int __init led_init(void)
{
    printk("led_init()\n");

    /* Request dynamic allocation of a device major number */
    if (alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME) < 0) {
        printk(KERN_DEBUG "Can't register device\n");
        return -1;
    }

    /* Create the led class */
    led_class = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(led_class)) printk("Bad class create\n");

    /* Connect the file operations with the cdev */
    cdev_init(&led_cdev, &led_fops);
    led_cdev.owner = THIS_MODULE;

    /* Connect the major/minor number to the cdev */
    if (cdev_add(&led_cdev, dev_number, 1)) {
        printk("Bad cdev add\n");
        return 1;
    }

    //class_device_create(led_class, NULL, dev_number,
    device_create(led_class, NULL, dev_number, NULL, DEVICE_NAME);

    /* Register this driver with parport */
    // int parport_register_driver (struct parport_driver * drv);
    if (parport_register_driver(&led_driver)) {
        printk(KERN_ERR "Bad Parport Register\n");
        return -EIO;
    }

    return 0;
}

/* Driver Exit */
void __exit led_cleanup(void)
{
    printk("led_cleanup()\n");

    //void parport_unregister_driver (struct parport_driver * arg);
    parport_unregister_driver(&led_driver);
    //class_device_destroy(led_class, MKDEV(MAJOR(dev_number), 0));
    device_destroy(led_class, dev_number);
    cdev_del(&led_cdev);
    class_destroy(led_class);
    unregister_chrdev_region(dev_number, 1);

    return;
}

module_init(led_init);
module_exit(led_cleanup);
MODULE_LICENSE("Dual BSD/GPL");
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义设备名称“led”
静态设备设备编号;/*分配的设备号*/
静态结构类*led_类;/*此设备所属的类*/
结构cdev led_cdev;/*关联cdev*/
结构pardevice*pdev;/*并行端口设备*/
/*发光二极管开路*/
int led_打开(结构索引节点*索引节点,结构文件*文件)
{
printk(内核信息)(pid:%d,cmd:%s)指示灯\u打开(主要:%d,次要:%d)\n“,
当前->pid,当前->通信,imajor(inode),iminor(inode));
返回0;
}
/*写入LED指示灯*/
ssize_t led_写入(结构文件*文件,常量字符*buf,大小计数,loff_t*ppos)
{
printk(内核信息)(pid:%d,cmd:%s)led_写入(计数:%d,*ppos:%lld)\n“,
当前->pid,当前->通信,计数,*ppos);
返回计数;
}
/*释放设备*/
int led_发布(结构索引节点*索引节点,结构文件*文件)
{
printk(内核信息)(pid:%d,cmd:%s)led_release()\n“,当前->pid,当前->通信);
返回0;
}
/*文件操作*/
静态结构文件\u操作指示灯\u fops={
.owner=此_模块,
.open=发光二极管(发光二极管)开路,
.write=led_write,
.release=发光二极管释放,
};
静态整数led_抢占(无效*句柄)
{
printk(内核信息)(pid:%d,cmd:%s)led_preempt()\n“,当前->pid,当前->通信);
返回1;
}
/*Parport连接方法*/
静态无效led_连接(结构参数*端口)
{
printk(内核信息)(pid:%d,cmd:%s)led_attach()\n“,当前->pid,当前->通信);
/*使用parport注册并行LED设备*/
pdev=端口\寄存器\设备(端口、设备\名称、,
led_抢占,空,
NULL,0,NULL);
如果(pdev==NULL)printk(“坏寄存器”\n);
}
/*Parport分离方法*/
静态无效led_分离(结构参数*端口)
{
printk(内核信息)(pid:%d,cmd:%s)led_detach()端口已分离\n“,当前->pid,当前->通信);
/*无所事事*/
parport_注销装置(pdev);
}
/*Parport驱动程序操作*/
静态结构参数驱动程序led驱动程序={
.name=设备名称,
.attach=led_attach,
.detach=led_detach,
};
/*驱动程序初始化*/
整数初始化led初始化(无效)
{
printk(“led_init()\n”);
/*请求动态分配设备主编号*/
if(alloc_chrdev_区域(&dev_编号,0,1,设备名称)<0){
printk(内核调试“无法注册设备”\n);
返回-1;
}
/*创建led类*/
led_类=类_创建(此_模块,设备名称);
if(IS_ERR(led_class))printk(“创建坏类”);
/*将文件操作与cdev连接*/
cdev_init(&led_cdev,&led_fops);
led_cdev.owner=此_模块;
/*将主/副编号连接到cdev*/
if(cdev添加(&led\U cdev,开发编号,1)){
printk(“不良cdev添加\n”);
返回1;
}
//类设备创建(led类、空、开发编号、,
设备创建(led类,空,设备编号,空,设备名称);
/*向parport注册此驱动程序*/
//int parport_寄存器_驱动程序(结构parport_驱动程序*drv);
if(参数寄存器驱动器和led驱动器)){
printk(KERN_ERR“坏参数寄存器”\n);
返回-EIO;
}
返回0;
}
/*驾驶员出口*/
void\u退出led\u清除(void)
{
printk(“led_cleanup()\n”);
//void parport_unregister_驱动程序(struct parport_driver*arg);
parport_注销_驱动程序(&led_驱动程序);
//类设备销毁(led类,MKDEV(主要(开发编号),0);
设备销毁(led类、设备编号);
cdev_del(&led_cdev);
破坏级(led级);
注销chrdev_地区(dev_编号,1);
回来
}
模块初始化(led初始化);
模块_退出(led_清除);
模块许可证(“双BSD/GPL”);

根据您的回复,我们现在知道了答案:


LED驱动程序依赖于parport.ko将驱动程序连接到通用并行端口。parport.ko依赖于parport_pc.ko实际检测/连接“pc风格的并行端口”。由于您禁用了parport_pc,并行端口将不会被检测到,附加事件也不会传递给您。

嘿嘿,在MITBBS上见过您。我也没有足够的背景知识。但是,您是否通过键入“dmesg | grep par”来检查您的parport驱动程序是否正确加载DMESG没有显示任何错误消息。从DMEG GEP PARP大量的DMEG GEP PARP中没有任何东西。这些[0 000000 ]在裸露硬件上引导的半虚拟化的内核(0.116221)没有APIC,用“LAPIC”引导参数启动以强制启用它。[0.143191 ]调节器假体:没有参数γ[2.789935 ]。非对称密钥解析器“x509”注册了parport驱动程序,但未正确加载或未找到并行端口?我的(尽管它只是Oracle虚拟机)显示:[11.650968]partport pc 00:04:即插即用ACPII报告已禁用在引导时加载parport_pc.ko和parport.ko。并在加载led.ko之前手动加载parport.ko。您的消息由parport_pc.ko生成。但是,我也尝试加载parport_pc.ko,然后加载insmod led.ko。这次是led_attach()调用了!!!我认为led.ko应该足够了,因为没有parport_pc.ko就没有错误或相关错误消息。不管怎样,它现在可以工作了。谢谢!我有点担心了