0

Google と ldd3 からの参照に従って、Linux でデバイス ドライバーを作成する方法を学ぼうとしています。以下のモジュールを挿入することはできますが、アプリケーションでデバイスを開こうとすると、カーネルがクラッシュしました。

コードとビルドの手順は次のとおりです。

#include <linux/module.h>       /* Needed by all modules */
#include <linux/kernel.h>       /* Needed for KERN_INFO */
#include <linux/init.h>         /* Needed for the macros */
#include <linux/ioport.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/param.h>
#include <linux/fs.h>
/* =============== Constant Definitions ============ */
#define SERIAL_IRQ 4
/* =============== Variable Definitions ============ */
static int SER_MAJOR =  0;
int ser_open(struct inode *inode, struct file *filp);
int ser_release(struct inode *inode, struct file *filp);

irqreturn_t my_ser_dev_isr(int irq,void *ser_data,struct pt_regs * pt_reg_var)
{
printk("\n\n -------   INTR raised   -----------\n\n");
return 0;
}

int ser_open(struct inode *inode, struct file *filp)
{
if(request_irq(SERIAL_IRQ,&my_ser_dev_isr,1,"my_ser_dev_intr",NULL))
{
printk("\n interrupt req failed\n");
}
else
{
enable_irq(SERIAL_IRQ);
printk("\n!!!!  ..obtained the requested interrupt and enabled\n");
}
}
int ser_release(struct inode *inode, struct file *filp)
{
disable_irq(SERIAL_IRQ);
free_irq(SERIAL_IRQ,NULL)   ;
}
static struct file_operations ser_fops = {
open: ser_open,
release: ser_release
};

void *p = NULL;
irqreturn_t my_ser_dev_isr (int, void *, struct pt_regs *);
static int __init hello_start(void)
{
int ret_val=-1;
int result;
printk(KERN_INFO "Loading hello module...\n");
printk(KERN_INFO "Hello world\n");
result = register_chrdev(SER_MAJOR,"SER_DEV",&ser_fops);
if(result < 0) 
{
printk(KERN_WARNING"Can't get major %d\n",SER_MAJOR);
return result;
}
if(SER_MAJOR == 0)
{
SER_MAJOR = result;
printk("SER DEV Major Number : %d",SER_MAJOR ); 
}   
return 0;   
}

static void __exit hello_end(void)
{
//  free_irq(SERIAL_IRQ,NULL);
//release_region(0x0031,1);
printk(KERN_INFO "Goodbye Mr.\n");
}
module_init(hello_start);
module_exit(hello_end);

モジュールの Makefile :

obj-m := hello.o
default:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

アクセスに使用するアプリケーションは次のとおりです。

#include <stdio.h> /* test.c */
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
static int dev;
int main(void)
{
char buff[40];
dev = open("/dev/my_ser_dev",O_RDONLY);
if(dev < 0) 
{
printf( "Device Open ERROR!\n");
exit(1);
}
printf("Please push the GPIO_16 port!\n");
//read(dev,buff,40);
// scanf("%s",buff);    
printf("%s\n",buff);
close(dev);
return 0;
}

insmodが与えた

[ 3837.312140] Loading hello module...
[ 3837.312147] Hello world
[ 3837.312218] SER DEV Major Number : 251

次に、mknod /dev/my_ser_dev c 251 0 を使用して特殊ファイルを作成しました。アプリケーションを実行すると、カーネル クラッシュが発生しました。UBUNTU 3.2.0-23-generic-pae を使用しています。

4

1 に答える 1

0

IRQ ハンドラーとして登録している関数のプロトタイプが間違っています。

irqreturn_t irq_handler(int, void *);

古いドキュメントを参照している可能性があります。

于 2012-07-30T17:54:00.827 に答える