您的位置:首页 > 其它

LDD3 short程序编译出错之修改

2014-11-03 18:49 579 查看
platform:i386

OS; ubuntu 10.04(linux2.6.32-38)

tools:gcc

short的编译:

liqinghan@ubuntu:~/examples/short$ make

make -C /lib/modules/2.6.32-38-generic/build M=/home/liqinghan/examples/short modules

make[1]: Entering directory `/usr/src/linux-headers-2.6.32-38-generic'

scripts/Makefile.build:49: *** CFLAGS was changed in "/home/liqinghan/examples/short/Makefile". Fix it to use EXTRA_CFLAGS. Stop.

make[1]: *** [_module_/home/liqinghan/examples/short] Error 2

make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-38-generic'

make: *** [default] Error 2

修改makefile,把CFLAGS改为EXTRA_CFLAGS即可!

liqinghan@ubuntu:~/examples/short$ vi Makefile

:%s/CFLAGS/EXTRA_CFLAGS/g

:wq

liqinghan@ubuntu:~/examples/short$ make

make -C /lib/modules/2.6.32-38-generic/build M=/home/liqinghan/examples/short modules

make[1]: Entering directory `/usr/src/linux-headers-2.6.32-38-generic'

CC [M] /home/liqinghan/examples/short/short.o

/home/liqinghan/examples/short/short.c:24:26: error: linux/config.h: No such file or directory

/home/liqinghan/examples/short/short.c: In function short_selfprobe?

/home/liqinghan/examples/short/short.c:514: error: SA_INTERRUPT?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:514: error: (Each undeclared identifier is reported only once

/home/liqinghan/examples/short/short.c:514: error: for each function it appears in.)

/home/liqinghan/examples/short/short.c:514: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

/home/liqinghan/examples/short/short.c:597:64: error: macro "INIT_WORK" passed 3 arguments, but takes just 2

/home/liqinghan/examples/short/short.c: In function short_init?

/home/liqinghan/examples/short/short.c:597: error: INIT_WORK?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:624: error: SA_SHIRQ?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:624: error: SA_INTERRUPT?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:625: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

/home/liqinghan/examples/short/short.c:638: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

/home/liqinghan/examples/short/short.c:658: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

make[2]: *** [/home/liqinghan/examples/short/short.o] Error 1

make[1]: *** [_module_/home/liqinghan/examples/short] Error 2

make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-38-generic'

make: *** [default] Error 2

修改把#include <linux/config.h>改为#include <linux/autoconf.h>

liqinghan@ubuntu:~/examples/short$ make

make -C /lib/modules/2.6.32-38-generic/build M=/home/liqinghan/examples/short modules

make[1]: Entering directory `/usr/src/linux-headers-2.6.32-38-generic'

CC [M] /home/liqinghan/examples/short/short.o

/home/liqinghan/examples/short/short.c: In function short_selfprobe?

/home/liqinghan/examples/short/short.c:514: error: SA_INTERRUPT?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:514: error: (Each undeclared identifier is reported only once

/home/liqinghan/examples/short/short.c:514: error: for each function it appears in.)

/home/liqinghan/examples/short/short.c:514: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

/home/liqinghan/examples/short/short.c:597:64: error: macro "INIT_WORK" passed 3 arguments, but takes just 2

/home/liqinghan/examples/short/short.c: In function short_init?

/home/liqinghan/examples/short/short.c:597: error: INIT_WORK?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:624: error: SA_SHIRQ?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:624: error: SA_INTERRUPT?undeclared (first use in this function)

/home/liqinghan/examples/short/short.c:625: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

/home/liqinghan/examples/short/short.c:638: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

/home/liqinghan/examples/short/short.c:658: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

make[2]: *** [/home/liqinghan/examples/short/short.o] Error 1

make[1]: *** [_module_/home/liqinghan/examples/short] Error 2

make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-38-generic'

make: *** [default] Error 2

1、对于SA_XX编译不通过,解决方法如下:

查看内核代码 interrupt.h文件

在linux2.6.32内核中没有

SA_INTERRUPT

SA_SHIRQ

..

SA_XX

的定义而在linux2.6.22却存在,可以根据SA_XX的定义如下:

//这里linux2.6.22和2.6.32都存在

#define IRQF_DISABLED 0x00000020

#define IRQF_SAMPLE_RANDOM 0x00000040

#define IRQF_SHARED 0x00000080

#define IRQF_PROBE_SHARED 0x00000100

#define IRQF_TIMER 0x00000200

#define IRQF_PERCPU 0x00000400

#define IRQF_NOBALANCING 0x00000800

#define IRQF_IRQPOLL 0x00001000

//这里linux2.6.22存在和2.6.32不存在

/*

* Migration helpers. Scheduled for removal in 9/2007

* Do not use for new code !

*/

static inline

unsigned long __deprecated deprecated_irq_flag(unsigned long flag)

{

return flag;

}

#define SA_INTERRUPT deprecated_irq_flag(IRQF_DISABLED)

#define SA_SAMPLE_RANDOM deprecated_irq_flag(IRQF_SAMPLE_RANDOM)

#define SA_SHIRQ deprecated_irq_flag(IRQF_SHARED)

#define SA_PROBEIRQ deprecated_irq_flag(IRQF_PROBE_SHARED)

#define SA_PERCPU deprecated_irq_flag(IRQF_PERCPU)

#define SA_TRIGGER_LOW deprecated_irq_flag(IRQF_TRIGGER_LOW)

#define SA_TRIGGER_HIGH deprecated_irq_flag(IRQF_TRIGGER_HIGH)

#define SA_TRIGGER_FALLING deprecated_irq_flag(IRQF_TRIGGER_FALLING)

#define SA_TRIGGER_RISING deprecated_irq_flag(IRQF_TRIGGER_RISING)

#define SA_TRIGGER_MASK deprecated_irq_flag(IRQF_TRIGGER_MASK)

可以知道SA_XX和IRQF_YY本质是一样,只不过通过一个函数返回来了而已。

所以只需要把SA_XX没有编译通过的改为对应的IRQF_YY既可。

2.INIT_WORK编译不通过,如下修改:

下面是linux2.3.32的INIT_WORK函数的定义

#ifdef CONFIG_LOCKDEP

#define INIT_WORK(_work, _func) \

do { \

static struct lock_class_key __key;\

\

(_work)->data = (atomic_long_t) WORK_DATA_INIT();\

lockdep_init_map(&(_work)->lockdep_map, #_work, &__key, 0);\

INIT_LIST_HEAD(&(_work)->entry);\

PREPARE_WORK((_work), (_func));\

} while (0)

#else

#define INIT_WORK(_work, _func) \

do { \

(_work)->data = (atomic_long_t) WORK_DATA_INIT();\

INIT_LIST_HEAD(&(_work)->entry);\

PREPARE_WORK((_work), (_func));\

} while (0)

#endif

而本程序用的却是这样子的,INIT_WORK(&short_wq, (void (*)(void *)) short_do_tasklet, NULL);明显这个INIT_WORK用的是老版本的INIT_WORK具体变化的版本,暂时未查,但是可以知道是在linux2.6.22以前的,因为在2.6.22的INIT_WORK和2.6.32是一样的。

我们只需要把第三个参数NULL去掉即可。

3、/home/liqinghan/examples/short/short.c:625: warning: passing argument 2 of request_irq?from incompatible pointer type

include/linux/interrupt.h:126: note: expected irq_handler_t?but argument is of type anum irqreturn_t (*)(int, void *, struct pt_regs *)?

这种警告,解决方法如下:

short是这样子使用的

irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs)

而在函数中struct pt_regs *regs这个参数根本没有用到。

在2.6.22和2.6.32中发现irq_handler_t函数指针如下:

typedef irqreturn_t (*irq_handler_t)(int, void *);

可知道short用的也是老版本的函数指针,所以我们只需要在使用了irq_handler_t的函数改为两个参数即可,因为第三个参数struct pt_regs *regs根本没用,所以不需要这个参数!

比如

irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs)

改为

irqreturn_t short_interrupt(int irq, void *dev_id)

即可

经过修改可以完成编译,却运行不起来,IO已被其他占用。

总结:

使用diff把之前的修改好的,做个补丁吧

diff -Naur ./short.c ./../../workspace/examples/short/short.c > short.patch

cat short.patch 如下:

--- ./short.c 2014-11-03 01:51:54.385718982 -0800

+++ ./../../workspace/examples/short/short.c
2014-11-03 01:43:10.960921160 -0800

@@ -43,7 +43,7 @@

#include <asm/io.h>

#define SHORT_NR_PORTS 8/* use 8 ports by default */

-

+#define _KERNEL_2_6_32_ /* for linux kernel 2.6.32 */

/*

* all of the parameters have no "short_" prefix, to save typing when

* specifying them at load time

@@ -332,8 +332,12 @@

.open
= short_open,

.release = short_release,

};

-

+#ifndef _KERNEL_2_6_32_

irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs)

+#else

+irqreturn_t short_interrupt(int irq, void *dev_id)

+#endif

+

{

struct timeval tv;

int written;

@@ -409,8 +413,12 @@

wake_up_interruptible(&short_queue); /* awake any reading process */

}

-

+#ifndef _KERNEL_2_6_32_

irqreturn_t short_wq_interrupt(int irq, void *dev_id, struct pt_regs *regs)

+#else

+irqreturn_t short_wq_interrupt(int irq, void *dev_id)

+#endif

+

{

/* Grab the current time information. */

do_gettimeofday((struct timeval *) tv_head);

@@ -427,8 +435,11 @@

/*

* Tasklet top half

*/

-

+#ifndef _KERNEL_2_6_32_

irqreturn_t short_tl_interrupt(int irq, void *dev_id, struct pt_regs *regs)

+#else

+irqreturn_t short_tl_interrupt(int irq, void *dev_id)

+#endif

{

do_gettimeofday((struct timeval *) tv_head); /* cast to stop 'volatile' warning */

short_incr_tv(&tv_head);

@@ -439,8 +450,11 @@

-

+#ifndef _KERNEL_2_6_32_

irqreturn_t short_sh_interrupt(int irq, void *dev_id, struct pt_regs *regs)

+#else

+irqreturn_t short_sh_interrupt(int irq, void *dev_id)

+#endif

{

int value, written;

struct timeval tv;

@@ -490,8 +504,11 @@

if (short_irq < 0)

printk("short: probe failed %i times, giving up\n", count);

}

-

+#ifndef _KERNEL_2_6_32_

irqreturn_t short_probing(int irq, void *dev_id, struct pt_regs *regs)

+#else

+irqreturn_t short_probing(int irq, void *dev_id)

+#endif

{

if (short_irq == 0) short_irq = irq;/* found */

if (short_irq != irq) short_irq = -irq; /* ambiguous */

@@ -510,9 +527,13 @@

* what has been acquired

*/

for (i = 0; trials[i]; i++)

+#ifndef _KERNEL_2_6_32_

tried[i] = request_irq(trials[i], short_probing,

SA_INTERRUPT, "short probe", NULL);

-

+#else

+ tried[i] = request_irq(trials[i], short_probing,

+ IRQF_DISABLED, "short probe", NULL);

+#endif

do {

short_irq = 0; /* none got, yet */

outb_p(0x10,short_base+2); /* enable */

@@ -594,8 +615,11 @@

* (unused) argument.

*/

/* this line is in short_init() */

+ #ifndef _KERNEL_2_6_32_

INIT_WORK(&short_wq, (void (*)(void *)) short_do_tasklet, NULL);

-

+ else

+ INIT_WORK(&short_wq,(void (*)(void *)) short_do_tasklet);

+ #endif

/*

* Now we deal with the interrupt: either kernel-based

* autodetection, DIY detection or default number

@@ -620,9 +644,15 @@

* force short_irq to -1.

*/

if (short_irq >= 0 && share > 0) {

+ #ifndef _KERNEL_2_6_32_

result = request_irq(short_irq, short_sh_interrupt,

SA_SHIRQ | SA_INTERRUPT,"short",

short_sh_interrupt);

+ #else

+ result = request_irq(short_irq, short_sh_interrupt,

+ IRQF_SHARED | IRQF_DISABLED,"short",

+ short_sh_interrupt);

+ #endif

if (result) {

printk(KERN_INFO "short: can't get assigned irq %i\n", short_irq);

short_irq = -1;

@@ -634,8 +664,13 @@

}

if (short_irq >= 0) {

+ #ifndef _KERNEL_2_6_32_

result = request_irq(short_irq, short_interrupt,

SA_INTERRUPT, "short", NULL);

+ #else

+ result = request_irq(short_irq, short_interrupt,

+ IRQF_DISABLED, "short", NULL);

+ #endif

if (result) {

printk(KERN_INFO "short: can't get assigned irq %i\n",

short_irq);

@@ -652,10 +687,17 @@

*/

if (short_irq >= 0 && (wq + tasklet) > 0) {

free_irq(short_irq,NULL);

+ #ifndef _KERNEL_2_6_32_

result = request_irq(short_irq,

tasklet ? short_tl_interrupt :

short_wq_interrupt,

SA_INTERRUPT,"short-bh", NULL);

+ #else

+ result = request_irq(short_irq,

+ tasklet ? short_tl_interrupt :

+ short_wq_interrupt,

+ IRQF_DISABLED,"short-bh", NULL);

+ #endif

if (result) {

printk(KERN_INFO "short-bh: can't get assigned irq %i\n",

short_irq);

//=======================================分割线==================================

liqinghan@ubuntu:~/workspace/examples/short$ sudo ./short_load

[sudo] password for liqinghan:

insmod: error inserting './short.ko': -1 No such device

liqinghan@ubuntu:~/workspace/examples/short$ tail /var/log/messages

Nov 3 17:38:35 ubuntu kernel: [ 2877.829664] short: can't get I/O port address 0x378

可以看出0x378已经被占用,

liqinghan@ubuntu:~/workspace/examples/short$ cat /proc/ioports

...

01f0-01f7 : 0000:00:07.1

01f0-01f7 : ata_piix

02f8-02ff : serial

0376-0376 : 0000:00:07.1

0376-0376 : ata_piix

0378-037a : parport0 //注:已被占用

03c0-03df : vga+

03f2-03f2 : floppy

03f4-03f5 : floppy

03f6-03f6 : 0000:00:07.1

03f6-03f6 : ata_piix

03f7-03f7 : floppy

03f8-03ff : serial

0cf0-0cf1 : pnp 00:01

0cf8-0cff : PCI conf1

1000-103f : 0000:00:07.3

...

查看没有使用的IO地址,

可以看出0x037B - 0x03C0这一段没有被占用,把 base改为 0x037B即可!

修改编译,加载模块!

liqinghan@ubuntu:~/workspace/examples/short$ cat /proc/ioports

...

01f0-01f7 : ata_piix

02f8-02ff : serial

0376-0376 : 0000:00:07.1

0376-0376 : ata_piix

0378-037a : parport0

037b-0382 : short //已经成功运行

03c0-03df : vga+

03f2-03f2 : floppy

03f4-03f5 : floppy

03f6-03f6 : 0000:00:07.1

03f6-03f6 : ata_piix

03f7-03f7 : floppy

03f8-03ff : serial

...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐