LDD3 short程序编译出错之修改

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
...


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

john_liqinghan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值