Linux kernel t是分配和共享的,它们是如何从硬件到系统冒出来的是一个巨大的课题,而这个问题实际上并不匹配。你最好在办公时间与你的教授会面——他们能够以适当的水平解释事情,并专注于与你的课程相关的部分。@katie我不是学生,只是为了自学。只是希望有人能给我打电话什么的。

Linux kernel t是分配和共享的,它们是如何从硬件到系统冒出来的是一个巨大的课题,而这个问题实际上并不匹配。你最好在办公时间与你的教授会面——他们能够以适当的水平解释事情,并专注于与你的课程相关的部分。@katie我不是学生,只是为了自学。只是希望有人能给我打电话什么的。,linux-kernel,operating-system,linux-device-driver,kernel-module,Linux Kernel,Operating System,Linux Device Driver,Kernel Module,t是分配和共享的,它们是如何从硬件到系统冒出来的是一个巨大的课题,而这个问题实际上并不匹配。你最好在办公时间与你的教授会面——他们能够以适当的水平解释事情,并专注于与你的课程相关的部分。@katie我不是学生,只是为了自学。只是希望有人能给我打电话什么的。我将不胜感激。:)1.一篇文章中的问题太多了。2.代码应该包含在问题帖子中,而不是链接。看,你的内核版本是什么?2.6.22.5?@Maquefel内核是3.13.0-37-generic #include <linux/module.h


t是分配和共享的,它们是如何从硬件到系统冒出来的是一个巨大的课题,而这个问题实际上并不匹配。你最好在办公时间与你的教授会面——他们能够以适当的水平解释事情,并专注于与你的课程相关的部分。@katie我不是学生,只是为了自学。只是希望有人能给我打电话什么的。我将不胜感激。:)1.一篇文章中的问题太多了。2.代码应该包含在问题帖子中,而不是链接。看,你的内核版本是什么?2.6.22.5?@Maquefel内核是3.13.0-37-generic
#include <linux/module.h>   // for init_module() 
#include <linux/etherdevice.h>  // for alloc_etherdev()
#include <linux/proc_fs.h>  // for create_proc_info_entry() 
#include <linux/interrupt.h>    // for request_irq(), free_irq()
#include <linux/wait.h>     // for init_wait_queue_head()
#include <linux/seq_file.h>

#define irqID       0x12    // temporary -- an unused IRQ
#define intID       0x55    // temporary -- IOAPIC mapped  

typedef struct  {
    struct tasklet_struct   my_rxtasklet;
    wait_queue_head_t   my_waitqueue;
    spinlock_t      my_lock;
} MY_DRIVERDATA;


int my_open( struct net_device * );
int my_stop( struct net_device * );
int my_hard_start_xmit( struct sk_buff *, struct net_device * );
irqreturn_t my_isr( int, void * );
void my_rx_handler( unsigned long );
int my_get_info( char *, char **, off_t, int );

char modname[] = "netframe";

static const struct net_device_ops mynetdev_ops={
    .ndo_open=my_open,
    .ndo_stop       = my_stop,
    .ndo_start_xmit = my_hard_start_xmit,
}; 

struct net_device  *netdev;

int my_get_info( char *buf, char **start, off_t off, int count )
{
    int len = 0;
    int i;
    *start = buf;
    if ( off == 0 )
    {
        len += sprintf( buf+len, "simulating an interrupt " );
        len += sprintf( buf+len, "by \'%s\' \n", netdev->name  );
        off += len;
    } 
    else
    {
        asm(" int %0 " : : "i" (intID) );
    }

    return  len;
}  

static int my_seq_open(struct inode *inode,struct file *file){
    printk(KERN_ALERT "DEBUG: Enter %s\n",__FUNCTION__);
    return single_open(file, &seq_proc_show,NULL);
}

struct file_operations fops = {
    .read=my_get_info,
};

static int __init my_init( void )
{ 
    printk( "<1>\nInstalling \'%s\' module\n", modname );

    if(!proc_create(modname,0666,NULL,&fops)){
        printk(KERN_INFO "ERROR! proc_create\n");
        remove_proc_entry(modname,NULL);
        return -1;
    }
    netdev = alloc_etherdev( sizeof( MY_DRIVERDATA ) );
    if ( !netdev ) return -ENOMEM;
    netdev->irq     = irqID;
    netdev->netdev_ops=&mynetdev_ops;

    return  register_netdev( netdev );  
} 

static void __exit my_exit(void )
{
    unregister_netdev( netdev );
    free_netdev( netdev );
    remove_proc_entry( modname, NULL );
    printk( "<1>Removing \'%s\' module\n", modname );
}

int my_open( struct net_device *dev ) 
{  
    MY_DRIVERDATA   *priv = netdev_priv(dev);
    unsigned long   devaddr = (unsigned long)dev;

    printk( "opening the \'%s\' interface \n", dev->name );

    spin_lock_init( &priv->my_lock );
    init_waitqueue_head( &priv->my_waitqueue );
    tasklet_init( &priv->my_rxtasklet, my_rx_handler, devaddr );

    if ( request_irq( dev->irq, my_isr, IRQF_SHARED, dev->name, dev ) < 0) return -EBUSY;

    netif_start_queue( dev );
    return 0; 
}

int my_stop( struct net_device *dev ) 
{ 
    MY_DRIVERDATA   *priv = netdev_priv(dev);

    printk( "stopping the \'%s\' interface \n", dev->name );

    free_irq( dev->irq, dev );

    tasklet_kill( &priv->my_rxtasklet );
    netif_stop_queue( dev );
    return 0; 
}

int my_hard_start_xmit( struct sk_buff *skb, struct net_device *dev )
{ 
    MY_DRIVERDATA   *priv = netdev_priv(dev);

    printk( "starting transmit on the \'%s\' interface \n", dev->name );

    dev->trans_start = jiffies;
    dev->stats.tx_packets += 1;
    dev->stats.tx_bytes += skb->len;

    wait_event_interruptible( priv->my_waitqueue, 1 );

    dev_kfree_skb( skb );
    return 0;
}

irqreturn_t my_isr( int irq, void *data )
{ 
    struct net_device   *dev = (struct net_device*)data;
    MY_DRIVERDATA   *priv = netdev_priv(dev);
    tasklet_schedule( &priv->my_rxtasklet );
    wake_up_interruptible( &priv->my_waitqueue );
    return  IRQ_HANDLED;
} 

void my_rx_handler( unsigned long data )
{
    struct net_device   *dev = (struct net_device *)data;
    struct sk_buff      *skb;
    int         rxbytes = 60;

    skb = dev_alloc_skb( rxbytes + 2 );
    skb->dev = dev;
    skb->protocol = eth_type_trans( skb, dev );
    skb->ip_summed = CHECKSUM_NONE;
    dev->stats.rx_packets += 1;
    dev->stats.rx_bytes += rxbytes;
    netif_rx( skb );
} 

module_init( my_init );
module_exit( my_exit );
MODULE_LICENSE("GPL");