1. linux涓嬪畨瑁呯紪璇戠綉鍗¢┍鍔ㄧ殑鏂规硶
瀹夎卨inux鎿嶄綔绯荤粺鍚庡彂鐜版病鏈夌綉鍗¢┍鍔锛岃〃鐜颁负
system 鈫 Administration 鈫 Network涓婬ardware鍒楄〃涓虹┖銆
浠ヤ笅涓哄畨瑁呯紪璇戠綉鍗¢┍鍔ㄧ殑杩囩▼锛屾湰浜烘槸鑿滈笩锛屼互涓嬫槸鎴戜粠缃戜笂鎵剧殑璧勬枡杩涜屾暣鐞嗭紝骞跺疄闄呮搷浣滅殑杩囩▼锛屼粎渚涘熼壌銆
涓.妫娴媗inux绯荤粺鍐呮牳鐗堟湰鍜岀綉鍗$被鍨嬶紝鐩稿叧鍛戒护濡備笅锛
uname -r 鏌ョ湅linux鍐呮牳鐗堟湰 (uname -a 鍙鏄剧ず鎵鏈変俊鎭)
lsmod 璁惧囧姞杞芥儏鍐
ls /usr/share/hwdata 鏌ョ湅纭浠惰惧
lspci 鏌ョ湅pci缃戝崱璁惧 ethernet controller 鍘傚晢鍜屽瀷鍙凤紝modprobe **** ****涓虹綉鍗″瀷鍙凤紝渚嬪 modprobe RTL8101E 锛屽傛灉鍑洪敊锛岃存槑妯″潡涓嶅瓨鍦锛岃ュ瀷鍙蜂笉璇嗗埆
鎴戝湪杩欎竴姝ユ椂鏌ユ壘涓嶅埌缃戝崱鍨嬪彿锛屾棤濂堝彧鑳界敱鍚屾椂閲囪喘鐨勫叾浠栫浉鍚屽瀷鍙烽勮厀in7鐨勭數鑴戜笅鏌ョ湅缃戝崱鍨嬪彿锛屾槸涓绗ㄥ姙娉曪紝鍢垮樋鈥︹
鎵惧埌缃戝崱鍨嬪彿鍚庡氨鍒伴┍鍔ㄤ箣瀹朵笅杞戒簡鐩稿簲缃戝崱鐨刲inux椹卞姩锛岃繖浜涢渶瑕佹牴鎹鑷宸辩殑瀹為檯鎯呭喌涓嬭浇锛屼笉澶氳翠簡锛岄噸鐐规槸鍚庨潰銆
浜.涓嬭浇缃戝崱椹卞姩
Intel_e1000e-1.9.5.zip 涓烘垜涓嬭浇鐨勬墍闇鐨勭綉鍗¢┍鍔锛岃繖涓鍦╨inux涓嬮渶鑷宸辩紪璇.
涓.瀹夎呯綉鍗¢┍鍔
1.妫娴嬬紪璇戦渶瑕佺敤鍒板唴鏍哥殑婧愪唬鐮佸寘鍜岀紪璇戠▼搴廹cc銆傛墍浠ュ傛灉娌℃湁鐨勮瘽,瑕佸厛瑁呫
[root@localhost ~]# rpm -qa|grep kernel
kernel-xen-2.6.18-8.el5
kernel-xen-devel-2.6.18-8.el5
kernel-headers-2.6.18-8.el5
[root@localhost ~]# rpm -qa|grep gcc
gcc-c++-4.1.1-52.el5
libgcc-4.1.1-52.el5
gcc-4.1.1-52.el5
gcc-gfortran-4.1.1-52.el5
濡傛灉缂哄皯kernel-xen-devel-2.6.18-8.el5锛屽彲浠ュ幓瀹夎呭厜鐩樼殑/Server/鐩褰曚笅锛屾壘鍒発ernel-xen-devel-2.6.18-8.el5.i686.rpm 鏂囦欢瀹夎呫
鎴戝緢骞歌繍锛屽畨瑁呯殑绯荤粺涓宸茬粡瀹夎呭ソ浜嗭紝鍛靛懙銆
2.缂栬瘧瀹夎呯綉鍗¢┍鍔
灏嗕笅杞界殑缃戝崱椹卞姩鏀惧埌/home鐩褰曚笅锛岃В鍘婭ntel_e1000e-1.9.5.zip鍖
unzip Intel_e1000e-1.9.5.zip
杩涘叆瑙e帇鍚庣殑鐩褰曞苟缂栬瘧瀹夎咃紝鍛戒护濡備笅锛
# cd e1000e-1.9.5/src
# make install
涓鑸鎯呭喌涓嬭В鍘嬬殑鐩褰曚腑浼氭湁涓涓猺eadme鏂囦欢锛岄噷闈㈣︾粏鍐欐槑浜嗙綉鍗″畨瑁呯殑姝ラわ紝寮虹儓寤鸿鍏堢湅readme锛屽畨瑁卹eadme涓姝ラゆ搷浣滀竴鑸涓嶄細鍑虹幇闂棰樸
瀹夎呭ソ鐨勬枃浠朵竴鑸浣嶄簬濡備笅鐩褰曚腑(kernel version浠ユ垜鐨勪负渚)
/lib/moles/2.6.18-194.el5xen/kernel/drivers/net/e1000e/e1000e.ko
insmod e1000e.ko
瀹夎呭畬姣曪紝鎴愬姛鍚庣郴缁熸彁绀虹綉缁滃凡杩炴帴锛岃存槑缃戝崱椹卞姩宸茬粡瑁呭ソ锛屼篃鍙浠ラ氳繃妫鏌system 鈫 Administration 鈫 Network涓婬ardware鍒楄〃銆
澶囨敞(浠ヤ笅涓虹綉涓婅祫鏂欙紝鏈瀹為檯楠岃瘉)锛
濡傛灉鎿嶄綔绯荤粺鍚鐢ㄤ簡鏀鎸乆EN鐨勫唴鏍革紝鈥滅‖浠垛濋夐」鍗¢噷浼氬嚭鐜颁袱涓缃戝崱锛宔th0鍜宲eth0銆
eth0灏辨槸鏄犲皠鍒皃eth0鐨;绯荤粺杩樹細鑷鍔ㄧ敓鎴愪竴涓獂enbr0鐨勭綉鍗;杩欎釜缃戝崱鏄涓篻uestOS鍋氭ˉ鎺ョ殑;vif0.0鏄鎸嘍omain0鐨勭涓鍧楃綉;vif0.1鎸嘍omain0鐨勭浜屽潡缃戝崱;
濡傛灉涓嶅噯澶囦娇鐢╔EN铏氭嫙鏈;鍙浠ュ湪鍚鍔ㄦ椂閫夋嫨娌℃湁xen鐨勫唴鏍革紝灏变笉浼氱敓鎴愯繖浜涢濆栫殑缃戝崱浜嗭細
姝ラや竴锛氬叧闂瓁end杩涚▼锛屼娇涔嬩笉闅忕郴缁熻嚜鍚鍔ㄣ
1.浣跨敤ntsysv鍛戒护杩涘叆鏈嶅姟绠$悊锛屽叧闂瓁end鏈嶅姟(绌烘牸閿鏄閫変腑鎴栬呭彇娑)
2.浣跨敤chkconfig鍛戒护锛
[root@localhost ~]# chkconfig --level 1 xend off
[root@localhost ~]# chkconfig --level 2 xend off
[root@localhost ~]# chkconfig --level 3 xend off
[root@localhost ~]# chkconfig --level 4 xend off
[root@localhost ~]# chkconfig --level 5 xend off
[root@localhost ~]# chkconfig --level 6 xend off
妫鏌xend鏄鍚﹂兘鏄鍏抽棴鐘舵侊細
[root@localhost ~]# chkconfig --list |grep xend
xend 0:鍏抽棴 1:鍏抽棴 2:鍏抽棴 3:鍏抽棴 4:鍏抽棴 5:鍏抽棴 6:鍏抽棴
xendomains 0:鍏抽棴 1:鍏抽棴 2:鍏抽棴 3:鍚鐢 4:鍚鐢 5:鍚鐢 6:鍏抽棴
淇鏀瑰畬姣曢噸鍚绯荤粺銆
姝ラや簩锛氳繘鍏ョ郴缁-绠$悊-缃戠粶 锛屽凡缁忚兘鐪嬪埌缃戝崱锛屽彲浠ラ厤缃甀P鍜孌NS銆
鐒跺悗淇鏀圭粦瀹歁AC鍦板潃锛
1.缃戝崱鐩稿叧鐨凾CP/IP缃戠粶閰嶇疆鏂囦欢鏄锛/etc/sysconfig/network-scripts/ifcfg-ethx銆傚叾涓瓁浠0寮濮嬶紝绗涓涓浠ュお缃戦厤缃鏂囦欢鍗筹細/etc/sysconfig/network-scripts/ifcfg-eth0銆備娇鐢╲i缂栬緫鍣ㄤ慨鏀硅繖涓鏂囦欢锛屼篃鍙浠ヤ慨鏀圭綉鍗MAC鍦板潃銆
鎶 HWADDR=ff:ff:ff:ff:ff
鏀逛负 MACADDR=00:1F:D0:64:9B:B7 MACADDR鍚庨潰鏄鑷宸辩殑mac鍦板潃
2. /etc/sysconfig/networking/profiles/default/ ifcfg-eth0
鎶 HWADDR=ff:ff:ff:ff:ff
鏀逛负 MACADDR=00:1F:D0:64:9B:B7 MACADDR鍚庨潰鏄鑷宸辩殑mac鍦板潃
2. 如何调试linux的网络驱动
如何根据oops定位代码行
我们借用linux设备驱动第二篇:构造和运行模块里面的hello world程序来演示出错的情况,含有错误代码的hello world如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <linux/init.h>
#include <linux/mole.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
char *p = NULL;
memcpy(p, "test", 4);
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
mole_init(hello_init);
mole_exit(hello_exit);
Makefile文件如下:
1
2
3
4
5
6
7
8
9
10
11
ifneq ($(KERNELRELEASE),)
obj-m := helloworld.o
else
KERNELDIR ?= /lib/moles/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) moles
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions moles.order Mole.symvers
很明显,以上代码的第8行是一个空指针错误。insmod后会出现下面的oops信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[ 459.516441] BUG: unable to handle kernel NULL pointer dereference at (null)
[ 459.516445]
[ 459.516448] PGD 0
[ 459.516450] Oops: 0002 [#1] SMP
[ 459.516452] Moles linked in: helloworld(OE+) vmw_vsock_vmci_transport vsock coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel aesni_intel vmw_balloon snd_ens1371 aes_x86_64 lrw snd_ac97_codec gf128mul glue_helper ablk_helper cryptd ac97_bus gameport snd_pcm serio_raw snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq snd_seq_device snd_timer vmwgfx btusb ttm snd drm_kms_helper drm soundcore shpchp vmw_vmci i2c_piix4 rfcomm bnep bluetooth 6lowpan_iphc parport_pc ppdev mac_hid lp parport hid_generic usbhid hid psmouse ahci libahci floppy e1000 vmw_pvscsi vmxnet3 mptspi mptscsih mptbase scsi_transport_spi pata_acpi [last unloaded: helloworld]
[ 459.516476] CPU: 0 PID: 4531 Comm: insmod Tainted: G OE 3.16.0-33-generic #44~14.04.1-Ubuntu
[ 459.516478] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 05/20/2014
[ 459.516479] task: ffff88003821f010 ti: ffff880038fa0000 task.ti: ffff880038fa0000
[ 459.516480] RIP: 0010:[<ffffffffc061400d>] [<ffffffffc061400d>] hello_init+0xd/0x30 [helloworld]
[ 459.516483] RSP: 0018:ffff880038fa3d40 EFLAGS: 00010246
[ 459.516484] RAX: ffff88000c31d901 RBX: ffffffff81c1a020 RCX: 000000000004b29f
[ 459.516485] RDX: 000000000004b29e RSI: 0000000000000017 RDI: ffffffffc0615024
[ 459.516485] RBP: ffff880038fa3db8 R08: 0000000000015e80 R09: ffff88003d615e80
[ 459.516486] R10: ffffea000030c740 R11: ffffffff81002138 R12: ffff88000c31d0c0
[ 459.516487] R13: 0000000000000000 R14: ffffffffc0614000 R15: ffffffffc0616000
[ 459.516488] FS: 00007f8a6fa86740(0000) GS:ffff88003d600000(0000) knlGS:0000000000000000
[ 459.516489] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 459.516490] CR2: 0000000000000000 CR3: 0000000038760000 CR4: 00000000003407f0
[ 459.516522] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 459.516524] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 459.516524] Stack:
[ 459.57] ffff880038fa3db8 ffffffff81002144 0000000000000001 0000000000000001
[ 459.516540] 0000000000000001 ffff880028ab5040 0000000000000001 ffff880038fa3da0
[ 459.516541] ffffffff8119d0b2 ffffffffc0616018 00000000bd1141ac ffffffffc0616018
[ 459.516543] Call Trace:
[ 459.516548] [<ffffffff81002144>] ? do_one_initcall+0xd4/0x210
[ 459.516550] [<ffffffff8119d0b2>] ? __vunmap+0xb2/0x100
[ 459.516554] [<ffffffff810ed9b1>] load_mole+0x13c1/0x1b80
[ 459.516557] [<ffffffff810e9560>] ? store_uevent+0x40/0x40
[ 459.516560] [<ffffffff810ee2e6>] SyS_finit_mole+0x86/0xb0
[ 459.516563] [<ffffffff8176be6d>] system_call_fastpath+0x1a/0x1f
[ 459.516564] Code: <c7> 04 25 00 00 00 00 74 65 73 74 31 c0 48 89 e5 e8 a2 86 14 c1 31
[ 459.516573] RIP [<ffffffffc061400d>] hello_init+0xd/0x30 [helloworld]
[ 459.516575] RSP <ffff880038fa3d40>
[ 459.516576] CR2: 0000000000000000
[ 459.516578] ---[ end trace 7c52cc8624b7ea60 ]---
下面简单分析下oops信息的内容。
由BUG: unable to handle kernel NULL pointer dereference at (null)知道出错的原因是使用了空指针。标红的部分确定了具体出错的函数。Moles linked in: helloworld表明了引起oops问题的具体模块。call trace列出了函数的调用信息。这些信息中其中标红的部分是最有用的,我们可以根据其信息找到具体出错的代码行。下面就来说下,如何定位到具体出错的代码行。
第一步我们需要使用objmp把编译生成的bin文件反汇编,我们这里就是helloworld.o,如下命令把反汇编信息保存到err.txt文件中:
1
objmp helloworld.o -D > err.txt
err.txt内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
helloworld.o: file format elf64-x86-64
Disassembly of section .text:
<span style="color:#ff0000;">0000000000000000 <init_mole>:</span>
0: e8 00 00 00 00 callq 5 <init_mole+0x5>
5: 55 push %rbp
6: 48 c7 c7 00 00 00 00 mov $0x0,%rdi
d: c7 04 25 00 00 00 00 movl $0x74736574,0x0
14: 74 65 73 74
18: 31 c0 xor %eax,%eax
1a: 48 89 e5 mov %rsp,%rbp
1d: e8 00 00 00 00 callq 22 <init_mole+0x22>
22: 31 c0 xor %eax,%eax
24: 5d pop %rbp
25: c3 retq
26: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
2d: 00 00 00
0000000000000030 <cleanup_mole>:
30: e8 00 00 00 00 callq 35 <cleanup_mole+0x5>
35: 55 push %rbp
36: 48 c7 c7 00 00 00 00 mov $0x0,%rdi
3d: 31 c0 xor %eax,%eax
3f: 48 89 e5 mov %rsp,%rbp
42: e8 00 00 00 00 callq 47 <cleanup_mole+0x17>
47: 5d pop %rbp
48: c3 retq
Disassembly of section .rodata.str1.1:
0000000000000000 <.rodata.str1.1>:
0: 01 31 add %esi,(%rcx)
2: 48 rex.W
3: 65 gs
4: 6c insb (%dx),%es:(%rdi)
5: 6c insb (%dx),%es:(%rdi)
6: 6f outsl %ds:(%rsi),(%dx)
7: 2c 20 sub $0x20,%al
9: 77 6f ja 7a <cleanup_mole+0x4a>
b: 72 6c jb 79 <cleanup_mole+0x49>
d: 64 0a 00 or %fs:(%rax),%al
10: 01 31 add %esi,(%rcx)
12: 47 6f rex.RXB outsl %ds:(%rsi),(%dx)
14: 6f outsl %ds:(%rsi),(%dx)
15: 64 fs
16: 62 (bad)
17: 79 65 jns 7e <cleanup_mole+0x4e>
19: 2c 20 sub $0x20,%al
1b: 63 72 75 movslq 0x75(%rdx),%esi
1e: 65 gs
1f: 6c insb (%dx),%es:(%rdi)
20: 20 77 6f and %dh,0x6f(%rdi)
23: 72 6c jb 91 <cleanup_mole+0x61>
25: 64 0a 00 or %fs:(%rax),%al
Disassembly of section .modinfo:
0000000000000000 <__UNIQUE_ID_license0>:
0: 6c insb (%dx),%es:(%rdi)
1: 69 63 65 6e 73 65 3d imul $0x3d65736e,0x65(%rbx),%esp
8: 44 75 61 rex.R jne 6c <cleanup_mole+0x3c>
b: 6c insb (%dx),%es:(%rdi)
c: 20 42 53 and %al,0x53(%rdx)
f: 44 2f rex.R (bad)
11: 47 50 rex.RXB push %r8
13: 4c rex.WR
...
Disassembly of section .comment:
0000000000000000 <.comment>:
0: 00 47 43 add %al,0x43(%rdi)
3: 43 3a 20 rex.XB cmp (%r8),%spl
6: 28 55 62 sub %dl,0x62(%rbp)
9: 75 6e jne 79 <cleanup_mole+0x49>
b: 74 75 je 82 <cleanup_mole+0x52>
d: 20 34 2e and %dh,(%rsi,%rbp,1)
10: 38 2e cmp %ch,(%rsi)
12: 32 2d 31 39 75 62 xor 0x62753931(%rip),%ch # 62753949 <cleanup_mole+0x62753919>
18: 75 6e jne 88 <cleanup_mole+0x58>
1a: 74 75 je 91 <cleanup_mole+0x61>
1c: 31 29 xor %ebp,(%rcx)
1e: 20 34 2e and %dh,(%rsi,%rbp,1)
21: 38 2e cmp %ch,(%rsi)
23: 32 00 xor (%rax),%al
Disassembly of section __mcount_loc:
0000000000000000 <__mcount_loc>:
由oops信息我们知道出错的地方是hello_init的地址偏移0xd。而有mp信息知道,hello_init的地址即init_mole的地址,因为hello_init即本模块的初始化入口,如果在其他函数中出错,mp信息中就会有相应符号的地址。由此我们得到出错的地址是0xd,下一步我们就可以使用addr2line来定位具体的代码行:
addr2line -C -f -e helloworld.o d
此命令就可以得到行号了。以上就是通过oops信息来定位驱动崩溃的行号。
其他调试手段
以上就是通过oops信息来获取具体的导致崩溃的代码行,这种情况都是用在遇到比较严重的错误导致内核挂掉的情况下使用的,另外比较常用的调试手段就是使用printk来输出打印信息。printk的使用方法类似printf,只是要注意一下打印级别,详细介绍在linux设备驱动第二篇:构造和运行模块中已有描述,另外需要注意的是大量使用printk会严重拖慢系统,所以使用过程中也要注意。
以上两种调试手段是我工作中最常用的,还有一些其他的调试手段,例如使用/proc文件系统,使用trace等用户空间程序,使用gdb,kgdb等,这些调试手段一般不太容易使用或者不太方便使用,所以这里就不在介绍了。
3. 如何调整Linux内核启动中的驱动初始化顺序
【问题】 此处我要实现的是将芯片的ID用于网卡MAC地址,网卡驱动是enc28j60_init。 但是,读取芯片ID的函数,在as352x_afe_init模块中,所以要先初始化as352x_afe_init。 此处,内核编译完之后,在生成的system.map中可以看到, enc28j60_init在as352x_afe_init之前,所以,无法去读芯片ID。 所以我们的目标是,将as352x_afe_init驱动初始化放到enc28j60_init之前, 然后才能读取芯片ID,才能用于网卡初始化的时候的,将芯片ID设置成网卡MAC地址。
【解决过程】
【1】
最简单想到的,是内核里面的
archarmmach-as352xcore.c
中,去改devices设备列表中的顺序。
enc28j60_init对应的是ssp_device,因为网卡初始化用到的是SPI驱动去进行和通讯的。
as352x_afe_init对应的是afe_device。
原先是:
把afe改到最前面:
但是,实际结果是,没有任何影响,连systemp.map生成的,那么模块初始化顺序,都没有任何变化。 也就说明,想要实现驱动加载顺序的改变,改core.c里面的设备列表顺序是没有用的。
更多linux内核视频教程文档资料免费领取后台私信 【内核】 自行获取.
Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂
【2】
在网上看到很多帖子,其说明的也很清楚了,就是:
Linux内核为不同驱动的加载顺序对应不同的优先级,定义了一些宏:
includelinuxinit.h
把自己的驱动的函数名用这些宏去定义之后, 就会对应不同的加载时候的优先级。
其中,我们写驱动中所用到的mole_init对应的是 #define mole_init(x) __initcall(x); 而 #define __initcall(fn) device_initcall(fn) 所以,驱动对应的加载的优先级为6
在上面的不同的优先级中, 数字越小,优先级越高。 同一等级的优先级的驱动,加载顺序是链接过程决定的,结果是不确定的,我们无法去手动设置谁先谁后。 不同等级的驱动加载的顺序是先优先级高,后优先级低,这是可以确定的。
所以,像我们之前在驱动中用:
所以,大家都是同一个优先级去初始化,
最后这些驱动加载的顺序,可以查看在根目录下,
生成的system.map:
此处就是由于 c0019920 t __initcall_i2c_dev_init6 c0019924 t __initcall_as352x_afe_i2c_init6 c0019928 t __initcall_as352x_afe_init6 在c00198e4 t __initcall_enc28j60_init6之前,所以我这里才要去改。。。 知道原理,能想到的,就是要么把as352x_afe_init改到enc28j60_init之前一级,即优先级为5。即在驱动中,调用:fs_initcall(as352x_afe_init);要么把enc28j60_init改到as352x_afe_init之后,即优先级为7即在驱动中,调用:late_initcall(enc28j60_init);但是,此处麻烦就麻烦在,如果把as352x_afe_init改到enc28j60_init之前一级,发现后面网卡初始化enc28j60_init中,虽然读取芯片ID对了,但是后面的IP-auto configure 有问题。所以放弃。 如果把enc28j60_init改到as352x_afe_init之后,但是,从system.map中看到的是,优先级为7的驱动中,明显有几个驱动,也是和网卡初始化相关的,所以,这样改,尝试后,还是失败了。 所以,没法简单的通过调整现有的驱动的顺序,去实现顺序的调整。最后,被逼无奈,想到了一个可以实现我们需求的办法,那就是,单独定义一个优先级,把afe相关的初始化都放到那里面去,这样,就可以保证,其他没什么相关的冲突了。最后证实,这样是可以实现目的的。
具体添加一个新的优先级的步骤如下: 1.定义新的优先级 includelinuxinit.h中:
2.用对应新的宏,定义我们的驱动:
做到这里,本以为可以了,但是编译后,在system.map中,发现之前优先级为7的那几个函数,被放到system.map最后了,而不是预想的,在优先级7之后,在
之前。最后,发现时没有把对应的链接文件中的宏加进去:
3.includeasm-genericvmlinux.lds.h
最后,再重新编译,就可以实现我们要的,和afe相关的驱动初始化,都在网卡enc28j60_init之前了。也就可以在网卡里面读芯片ID了。当然,对应编译生成的system.map文件中,对应的通过mole_init定义的驱动,优先级也都变成7了。而late_initcall对应优先级8了。 注:当前开发板arm的板子,所以,对应的load 脚本在:
linux-2.6.28.4archarmkernelvmlinux.lds 看起来,应该是这个文件: linux-2.6.28.4archarmkernelvmlinux.lds.S 生成上面那个脚本的。vmlinux.lds中的这一行:
就是将之前那些对应的init类型的函数,展开,放到这对应的位置。
【3】 不过,最后的最后,竟然发现网卡还是工作不正常,结果第二天,无意间发现是网卡地址设置导致网卡工作不正常的。 也就是说,实际是直接将afe设置到原先的优先级5就可以的,而不用这么麻烦去改系统的东西的...
不过,至少这也是一种办法,虽然不是那么的好...
4. linux下无线网卡如何驱动
linux下无线网卡具体驱动的操作方法如下:
1、首先需要确定网卡的类型,打开linux的输入窗专口,然后继续在linux终端属下输入lsusb命令,此时在输出栏的第一行可以查看网卡类型,记录下来。