linux網路設備驅動
『壹』 如何調試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等,這些調試手段一般不太容易使用或者不太方便使用,所以這里就不在介紹了。
『貳』 編寫Linux網路驅動程序需要注意些什麼
需要共享的話,在申請的時候指明共享方式。系統提供的request_irq()調用的定義: int request_irq(unsigned int irq, void (*handler)(int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname, void *dev_id); 如果共享中斷,irqflags設置SA_SHIRQ屬性,這樣就允許別的設備申請同一個中斷。需要注意所有用到這個中斷的設備在調用request_irq()都必須設置這個屬性。系統在回調每個中斷處理程序時,可以用dev_id這個參數找到相應的設備。系統在回調每個中斷處理程序時,可以用dev_id這個參數找到相應的設備。一般dev_id就設為device結構本身。系統處理共享中斷是用各自的dev_id參數依次調用每一個中斷處理程序。2 硬體發送忙時的處理 主CPU的處理能力一般比網路發送要快,所以經常會遇到系統有數據要發,但上一包數據網路設備還沒發送完。因為在Linux里網路設備驅動程序一般不做數據緩存,不能發送的數據都是通知系統發送不成功,所以必須要有一個機制在硬體不忙時及時通知系統接著發送下面的數據。 一般對發送忙的處理在前面設備的發送方法(hard_start_xmit)里已經描述過,即如果發送忙,置tbusy為1。處理完發送數據後,在發送結束中斷里清tbusy,同時用mark_bh()調用通知系統繼續發送。 但在具體實現我的驅動程序時發現,這樣的處理系統好象並不能及時地知道硬體已經空閑了,即在mark_bh()以後,系統要等一段時間才會接著發送。造成發送效率很低。2M線路只有10%不到的使用率。內核版本為2.0.35。 我最後的實現是不把tbusy置1,讓系統始終認為硬體空閑,但是報告發送不成功。系統會一直嘗試重發。這樣處理就運行正常了。但是遍循內核源碼中的網路驅動程序,似乎沒有這樣處理的。不知道症結在哪裡。 3 流量控制(flow control) 網路數據的發送和接收都需要流量控制。這些控制是在系統里實現的,不需要驅動程序做工作。每個設備數據結構里都有一個參數dev->tx_queue_len,這個參數標明發送時最多緩存的數據包。在Linux系統里乙太網設備(10/100Mbps)標明發送時最多緩存的數據包。在Linux系統里乙太網設備(10/100Mbps)tx_queue_len一般設置為100,串列線路(非同步串口)為10。實際上如果看源碼可以知道,設置了dev->tx_queue_len並不是為緩存這些數據申請了空間。這個參數只是在收到協議層的數據包時判斷發送隊列里的數據是不是到了tx_queue_len的限度,以決定這一包數據加不加進發送隊列。發送時另一個方面的流控是更高層協議的發送窗口(TCP協議里就有發送窗口)。達到了窗口大小,高層協議就不會再發送數據。 接收流控也分兩個層次。netif_rx()緩存的數據包有限制。另外高層協議也會有一個最大的等待處理的數據量。 發送和接收流控處理在net/core/dev.c的do_dev_queue_xmit()和netif_rx()中。 4 調試很多Linux的驅動程序都是編譯進內核的,形成一個大的內核文件。但對調試來說,這是相當麻煩的。調試驅動程序可以用mole方式載入。支持模塊方式的驅動程序必須提供兩個函數:int init_mole(void)和void cleanup_mole(void)。init_mole()在載入此模塊時調用,在這個函數里可以register_netdev()注冊設備。init_mole()返回0表示成功,返回負表示失敗。cleanup_mole()在驅動程序被卸載時調用,清除佔用的資源,調用unregister_netdev()。 模塊可以動態地載入、卸載。在2.0.xx版本里,還有kerneld自動載入模塊,但是2.2.xx中已經取消了kerneld。手工載入使用insmod命令,卸載用rmmod命令,看內核中的模塊用lsmod命令。 編譯驅動程序用gcc,主要命令行參數-DKERNEL -DMODULE。並且作為模塊載入的驅動程序,只編譯成obj形式(加-c參數)。編譯好的目標文放/lib/moles/2.x.xx/misc下,在啟動文件里用insmod載入。 Linux內核源代碼 《The Linux Kernel Hacker's Guide》by Michael K. Johnson 《Linux Kernel Mole Programming Guide》by Ori Pomerantz 《Linux下的設備驅動程》by olly in BBS水木清華站 可以選擇一個模板作為開始,內核源代碼里有一個網路驅動程序的模板,drivers/net/skeleton.c。裡麵包含了驅動程序的基本內容。但這個模板是以乙太網設備為對象的,乙太網的處理在Linux系統里有特殊「待遇」,所以如果不是乙太網設備,有些細節上要注意,主要在初始化程序里。 最後,多參照別人寫的程序,聽聽其他開發者的經驗之談大概是最有效的幫助了。
『叄』 Linux有哪三類設備驅動程序並說說這些設備驅動程序的功能
(1)塊設備
塊設備以數據塊的形式存放數據,如NAND Flash以頁為單位存儲數據,並採用mount方式掛載塊設備。塊設備還需通過建立Flash文件系統,如YAFFS、JFFS等,用於規範文件和目錄在存儲介質上的組織。這類型的設備已經在Linux內核中載入,不需要再做移植。
(2)網路設備
網路設備是面向數據包的接收和發送而設計的。它並不對應於文件系統(/dev目錄下)的節點,而是由系統分配一個唯一的名字(如eth0)。
(3)字元設備
字元設備指能夠像位元組流串列順序依次進行訪問的設備,對它的讀寫是以位元組為單位。除了網路設備外,字元設備和塊設備都是通過文件系統的系統調用介面open()、close()、write()、read()等函數既可以訪問,應用程序可以通過打開設備文件(如UART0設備:/dev/ttyS0)來訪問該設備。
『肆』 Linux網路設備驅動的結構
Linux網路設備驅動程序的體系結構從上到下可以劃分為4層,依次為網路協議介面層、網路設備介面層、提供實際功能的設備驅動功能層以及網路設備與媒介層,這4層的作用如下所示。
1)網路協議介面層向網路層協議提供統一的數據包收發介面,不論上層協議是ARP,還是IP,都通過dev_queue_xmit() 函數發送數據,並通過netif rx ()函數接收數據。這一層的存在使得上層協議獨立於具體的設備。
2)網路設備介面層向協議介面層提供統一的用於描述具體網路設備屬性和操作的結構體net device,該結構體是設備驅動功能層中各函數的容器。實際上,網路設備介面層從宏觀上規劃了具體操作硬體的設備驅動功能層的結構。
3)設備驅動功能層的各函數是網路設備介面層net_device數據結構的具體成員,是驅使網路設備硬體完成相應動作的程序,它通過hard_start_ xmit ()函數啟動發送操作,並通過網路設備上的中斷觸發接收操作。
4)網路設備與媒介層是完成數據包發送和接收的物理實體,包括網路適配器和具體的傳輸媒介,網路適配器被設備驅動功能層中的函數在物理上驅動。對於Linux系統而言,網路設備和媒介都可以是虛擬的。
『伍』 Linux網路設備驅動的具體結構
Linux網路設備驅動程序的體系結構從上到下可以劃分為4層,依次為網路協議介面層、網路設備介面層、提供實際功能的設備驅動功能層以及網路設備與媒介層,這4層的作用如下所示:
1)網路協議介面層向網路層協議提供統一的數據包收發介面,不論上層協議是ARP,還是IP,都通過dev_queue_xmit() 函數發送數據,並通過netif rx ()函數接收數據。這一層的存在使得上層協議獨立於具體的設備。
2)網路設備介面層向協議介面層提供統一的用於描述具體網路設備屬性和操作的結構體net device,該結構體是設備驅動功能層中各函數的容器。實際上,網路設備介面層從宏觀上規劃了具體操作硬體的設備驅動功能層的結構。
3)設備驅動功能層的各函數是網路設備介面層net_device數據結構的具體成員,是驅使網路設備硬體完成相應動作的程序,它通過hard_start_ xmit ()函數啟動發送操作,並通過網路設備上的中斷觸發接收操作。
4)網路設備與媒介層是完成數據包發送和接收的物理實體,包括網路適配器和具體的傳輸媒介,網路適配器被設備驅動功能層中的函數在物理上驅動。對於Linux系統而言,網路設備和媒介都可以是虛擬的。
『陸』 Linux網路設備驅動完成數據包發送的流程
從網路設備驅動程序的結構分析可知,Linux網路子系統在發送數據包時,會調用驅動程序提供的hard_start_transmit()函數,該函數用於啟動數據包的發送。在設備初始化的時候,這個函數指針需被初始化以指向設備的xxx_tx ()函數。網路設備驅動完成數據包發送的流程如下:1)網路設備驅動程序從上層協議傳遞過來的sk_buff參數獲得數據包的有效數據和長度,將有效數據放入臨時緩沖區。2)對於乙太網,如果有效數據的長度小於乙太網沖突檢測所要求數據幀的最小長度ETH ZLEN,則給臨時緩沖區的末尾填充0。3)設置硬體的寄存器,驅使網路設備進行數據發送操作。特別要強調對netif_ stop_queue()的調用,當發送隊列為滿或因其他原因來不及發送當前上層傳下來的數據包時,則調用此函數阻止上層繼續向網路設備驅動傳遞數據包。當忙於發送的數據包被發送完成後,在以TX結束的中斷處理中,應該調用netif_wake_queue ()喚醒被阻塞的上層,以啟動它繼續向網路設備驅動傳送數據包。當數據傳輸超時時,意味著當前的發送操作失敗或硬體已陷入未知狀態,此時,數據包發送超時處理函數xxx _tx _timeout ()將被調用。這個函數也需要調用由Linux內核提供的netif_wake _queue()函數以重新啟動設備發送隊列。
『柒』 linux驅動有哪些
1、將驅動程序文件bcm5700src.rpm復制到一個臨時目錄中,並在此目錄中運行以下命令;
2、運行以下命令切換到驅動目錄中;
3、此目錄中會生成一個名字為bcm5700.spec的文件,運行以下命令對驅動程序進行編譯;
4、運行以下命令切換到RPM目錄中;
5、運行以下命令安裝驅動程序;
6、運行以下命令載入驅動模塊;
7、運行kudzu命令,系統會自動搜索到硬體,進行配置即可。
linux是文件型系統,在linux中,一切皆文件,所有硬體都會在對應的目錄(/dev)下面用相應的文件表示。 文件系統的linux下面,都有對於文件與這些設備關聯的,訪問這些文件就可以訪問實際硬體。 通過訪問文件去操作硬體設備,一切都會簡單很多,不需要再調用各種復雜的介面。 直接讀文件,寫文件就可以向設備發送、接收數據。 按照讀寫存儲數據方式,我們可以把設備分為以下幾種:字元設備(character device)、塊設備(Block device)和網路設備( network interface)。
字元設備(character device):指應用程序採用字元流方式訪問的設備。這些設備節點通常為傳真、虛擬終端和串口數據機、鍵盤之類設備提供流通信服務, 它通常只支持順序訪問。字元設備在實現時,大多不使用緩存器。系統直接從設備讀取/寫入每一個字元。
塊設備(Block device):通常支持隨機存取和定址,並使用緩存器,支持mount文件系統。典型的塊設備有硬碟、SD卡、快閃記憶體等,但此類設備一般不需要自己開發,linux對此提過了大部分的驅動。
網路設備(network interface):是一種特殊設備,它並不存在於/dev下面,主要用於網路數據的收發。網路驅動同塊驅動最大的不同在於網路驅動非同步接受外界數據,而塊驅動只對內核的請求作出響應。
上述設備中,字元設備驅動程序適合於大多數簡單的硬體設備,算是各類驅動程序中最簡單的一類,一般也是從這類驅動開始學習,然後再開始學習採用IIC、SPI等通訊介面的一些設備驅動。可以基於此類驅動調試LKT和LCS系列加密晶元。注意7位IIC地址是0x28。
『捌』 linux虛擬機怎麼安裝無線網卡驅動
linux虛擬機可通過以下方式安裝無線網卡驅動:
1、打開「計算機」,單擊「設備管理器」,在設備管理器瀏覽窗口找到網路適配器,以便查詢看無線網卡驅動以及設備是否已正確安裝;
2、在計算機裡面點擊虛擬機名稱,打開對應的虛擬機設備;
3、點擊「虛擬機」菜單,從其下拉菜單中選擇「可移動設置」,並從無線網卡驅動名稱中選擇「與主機連接或斷開連接」項,並點擊確定;
4、通過以上步驟,此時主機中的無線網卡已被彈出,而虛擬機中的無線網卡驅動已安裝成功並且可以正常使用。
『玖』 Linux網路設備驅動編程有哪些
需要一定的努力才可以學好:
Linux設備驅動是linux內核的一部分,是用來屏蔽硬體細節,為上層提供標准介面的一種技術手段。為了能夠編寫出質量比較高的驅動程序,要求工程師必須具備以下幾個方面的知識:
1、
熟悉處理器的性能
如:處理器的體系結構、匯編語言、工作模式、異常處理等。對於初學者來說,在還不熟悉驅動編寫方法的情況下,可以先不把重心放在這一項上,因為可能因為它的枯燥、抽象而影響到你對設備驅動的興趣。隨著你不斷地熟悉驅動的編寫,你會很自然的意識到此項的重要性。
2、掌握驅動目標的硬體工作原理及通訊協議
如:串口控制器、顯卡控制器、硬體編解碼、存儲卡控制器、I2C通訊、SPI通訊、USB通訊、SDIO通訊、I2S通訊、PCI通訊等。編寫設備驅動的前提就是需要了解設備的操作方法,所以這些內容的重要程度不言而喻。但不是說要把所有設備的操作方法都熟悉了以後才可以寫驅動,你只需要了解你要驅動的硬體就可以了。
『拾』 linux的設備驅動一般分為幾類各有什麼特點
大致分為三類,字元驅動,塊設備驅動,網路設備驅動。
字元設備可以看成是用位元組流存取的文件
塊設備則可以看成是可以任意存取位元組數的字元設備,在應用上只是內核管理數據方式不同
網路設備可以是一個硬體設備,或者是軟體設備,他沒有相應的read write,它是面向流的一種特殊設備。