導航:首頁 > 操作系統 > linuxqudong

linuxqudong

發布時間:2022-09-23 07:34:27

linux的設備驅動一般分為幾類各有什麼特點

大致分為三類,字元驅動,塊設備驅動,網路設備驅動。
字元設備可以看成是用位元組流存取的文件

塊設備則可以看成是可以任意存取位元組數的字元設備,在應用上只是內核管理數據方式不同

網路設備可以是一個硬體設備,或者是軟體設備,他沒有相應的read write,它是面向流的一種特殊設備。

⑵ 如何編寫Linux 驅動程序

如何編寫Linux設備驅動程序
回想學習Linux操作系統已經有近一年的時間了,前前後後,零零碎碎的一路學習過來,也該試著寫的東西了。也算是給自己能留下一點記憶和回憶吧!由於完全是自學的,以下內容若有不當之處,還請大家多指教。
Linux是Unix操作系統的一種變種,在Linux下編寫驅動程序的原理和思想完全類似於其他的Unix系統,但它dos或window環境下的驅動程序有很大的區別。在Linux環境下設計驅動程序,思想簡潔,操作方便,功能也很強大,但是支持函數少,只能依賴kernel中的函數,有些常用的操作要自己來編寫,而且調試也不方便。
以下的一些文字主要來源於khg,johnsonm的Write linux device driver,Brennan's Guide to Inline Assembly,The Linux A-Z,還有清華BBS上的有關device driver的一些資料。
一、Linux device driver 的概念
系統調用是操作系統內核和應用程序之間的介面,設備驅動程序是操作系統內核和機器硬體之間的介面。設備驅動程序為應用程序屏蔽了硬體的細節,這樣在應用程序看來,硬體設備只是一個設備文件,應用程序可以象操作普通文件一樣對硬體設備進行操作。設備驅動程序是內核的一部分,它完成以下的功能:
1、對設備初始化和釋放。
2、把數據從內核傳送到硬體和從硬體讀取數據。
3、讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據。
4、檢測和處理設備出現的錯誤。
在Linux操作系統下有三類主要的設備文件類型,一是字元設備,二是塊設備,三是網路設備。字元設備和塊設備的主要區別是:在對字元設備發出讀/寫請求時,實際的硬體I/O一般就緊接著發生了,塊設備則不然,它利用一塊系統內存作緩沖區,當用戶進程對設備請求能滿足用戶的要求,就返回請求的數據,如果不能,就調用請求函數來進行實際的I/O操作。塊設備是主要針對磁碟等慢速設備設計的,以免耗費過多的CPU時間來等待。
已經提到,用戶進程是通過設備文件來與實際的硬體打交道。每個設備文件都都有其文件屬性(c/b),表示是字元設備還是塊設備?另外每個文件都有兩個設備號,第一個是主設備號,標識驅動程序,第二個是從設備號,標識使用同一個設備驅動程序的不同的硬體設備,比如有兩個軟盤,就可以用從設備號來區分他們。設備文件的的主設備號必須與設備驅動程序在登記時申請的主設備號一致,否則用戶進程將無法訪問到驅動程序。
最後必須提到的是,在用戶進程調用驅動程序時,系統進入核心態,這時不再是搶先式調度。也就是說,系統必須在你的驅動程序的子函數返回後才能進行其他的工作。如果你的驅動程序陷入死循環,不幸的是你只有重新啟動機器了,然後就是漫長的fsck。
讀/寫時,它首先察看緩沖區的內容,如果緩沖區的數據未被處理,則先處理其中的內容。
如何編寫Linux操作系統下的設備驅動程序

二、實例剖析
我們來寫一個最簡單的字元設備驅動程序。雖然它什麼也不做,但是通過它可以了解Linux的設備驅動程序的工作原理。把下面的C代碼輸入機器,你就會獲得一個真正的設備驅動程序。
#define __NO_VERSION__
#include <linux/moles.h>
#include <linux/version.h>
char kernel_version [] = UTS_RELEASE;
這一段定義了一些版本信息,雖然用處不是很大,但也必不可少。Johnsonm說所有的驅動程序的開頭都要包含<linux/config.h>,一般來講最好使用。
由於用戶進程是通過設備文件同硬體打交道,對設備文件的操作方式不外乎就是一些系統調用,如 open,read,write,close…, 注意,不是fopen, fread,但是如何把系統調用和驅動程序關聯起來呢?這需要了解一個非常關鍵的數據結構:
struct file_operations
{
int (*seek) (struct inode * ,struct file *, off_t ,int);
int (*read) (struct inode * ,struct file *, char ,int);
int (*write) (struct inode * ,struct file *, off_t ,int);
int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);
int (*select) (struct inode * ,struct file *, int ,select_table *);
int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);
int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);
int (*open) (struct inode * ,struct file *);
int (*release) (struct inode * ,struct file *);
int (*fsync) (struct inode * ,struct file *);
int (*fasync) (struct inode * ,struct file *,int);
int (*check_media_change) (struct inode * ,struct file *);
int (*revalidate) (dev_t dev);
}

這個結構的每一個成員的名字都對應著一個系統調用。用戶進程利用系統調用在對設備文件進行諸如read/write操作時,系統調用通過設備文件的主設備號找到相應的設備驅動程序,然後讀取這個數據結構相應的函數指針,接著把控制權交給該函數。這是linux的設備驅動程序工作的基本原理。既然是這樣,則編寫設備驅動程序的主要工作就是編寫子函數,並填充file_operations的各個域。
下面就開始寫子程序。
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include<linux/config.h>
#include <linux/errno.h>
#include <asm/segment.h>
unsigned int test_major = 0;
static int read_test(struct inode *node,struct file *file,char *buf,int count)
{
int left;
if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )
return -EFAULT;
for(left = count ; left > 0 ; left--)
{
__put_user(1,buf,1);
buf++;
}
return count;
}

這個函數是為read調用准備的。當調用read時,read_test()被調用,它把用戶的緩沖區全部寫1。buf 是read調用的一個參數。它是用戶進程空間的一個地址。但是在read_test被調用時,系統進入核心態。所以不能使用buf這個地址,必須用__put_user(),這是kernel提供的一個函數,用於向用戶傳送數據。另外還有很多類似功能的函數。請參考Robert著的《Linux內核設計與實現》(第二版)。然而,在向用戶空間拷貝數據之前,必須驗證buf是否可用。這就用到函數verify_area。
static int write_tibet(struct inode *inode,struct file *file,const char *buf,int count)
{
return count;
}
static int open_tibet(struct inode *inode,struct file *file )
{
MOD_INC_USE_COUNT;
return 0;
}
static void release_tibet(struct inode *inode,struct file *file )
{
MOD_DEC_USE_COUNT;
}

這幾個函數都是空操作。實際調用發生時什麼也不做,他們僅僅為下面的結構提供函數指針。
struct file_operations test_fops = {
NULL,
read_test,
write_test,
NULL, /* test_readdir */
NULL,
NULL, /* test_ioctl */
NULL, /* test_mmap */
open_test,
release_test,
NULL, /* test_fsync */
NULL, /* test_fasync */
/* nothing more, fill with NULLs */
};
這樣,設備驅動程序的主體可以說是寫好了。現在要把驅動程序嵌入內核。驅動程序可以按照兩種方式編譯。一種是編譯進kernel,另一種是編譯成模塊(moles),如果編譯進內核的話,會增加內核的大小,還要改動內核的源文件,而且不能動態的卸載,不利於調試,所以推薦使用模塊方式。
int init_mole(void)
{
int result;
result = register_chrdev(0, "test", &test_fops);
if (result < 0) {
printk(KERN_INFO "test: can't get major number\n");
return result;
}
if (test_major == 0) test_major = result; /* dynamic */
return 0;
}

在用insmod命令將編譯好的模塊調入內存時,init_mole 函數被調用。在這里,init_mole只做了一件事,就是向系統的字元設備表登記了一個字元設備。register_chrdev需要三個參數,參數一是希望獲得的設備號,如果是零的話,系統將選擇一個沒有被佔用的設備號返回。參數二是設備文件名,參數三用來登記驅動程序實際執行操作的函數的指針。
如果登記成功,返回設備的主設備號,不成功,返回一個負值。
void cleanup_mole(void)
{
unregister_chrdev(test_major,"test");
}
在用rmmod卸載模塊時,cleanup_mole函數被調用,它釋放字元設備test在系統字元設備表中佔有的表項。
一個極其簡單的字元設備可以說寫好了,文件名就叫test.c吧。
下面編譯 :
$ gcc -O2 -DMODULE -D__KERNEL__ -c test.c
得到文件test.o就是一個設備驅動程序。
如果設備驅動程序有多個文件,把每個文件按上面的命令行編譯,然後
ld -r file1.o file2.o -o molename。
驅動程序已經編譯好了,現在把它安裝到系統中去。
$ insmod –f test.o
如果安裝成功,在/proc/devices文件中就可以看到設備test,並可以看到它的主設備號。要卸載的話,運行 :
$ rmmod test
下一步要創建設備文件。
mknod /dev/test c major minor
c 是指字元設備,major是主設備號,就是在/proc/devices里看到的。
用shell命令
$ cat /proc/devices
就可以獲得主設備號,可以把上面的命令行加入你的shell script中去。
minor是從設備號,設置成0就可以了。
我們現在可以通過設備文件來訪問我們的驅動程序。寫一個小小的測試程序。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
int testdev;
int i;
char buf[10];
testdev = open("/dev/test",O_RDWR);
if ( testdev == -1 )
{
printf("Cann't open file \n");
exit(0);
}
read(testdev,buf,10);
for (i = 0; i < 10;i++)
printf("%d\n",buf[i]);
close(testdev);
}

編譯運行,看看是不是列印出全1 ?
以上只是一個簡單的演示。真正實用的驅動程序要復雜的多,要處理如中斷,DMA,I/O port等問題。這些才是真正的難點。請看下節,實際情況的處理。
如何編寫Linux操作系統下的設備驅動程序
三、設備驅動程序中的一些具體問題
1。 I/O Port。
和硬體打交道離不開I/O Port,老的ISA設備經常是佔用實際的I/O埠,在linux下,操作系統沒有對I/O口屏蔽,也就是說,任何驅動程序都可對任意的I/O口操作,這樣就很容易引起混亂。每個驅動程序應該自己避免誤用埠。
有兩個重要的kernel函數可以保證驅動程序做到這一點。
1)check_region(int io_port, int off_set)
這個函數察看系統的I/O表,看是否有別的驅動程序佔用某一段I/O口。
參數1:I/O埠的基地址,
參數2:I/O埠佔用的范圍。
返回值:0 沒有佔用, 非0,已經被佔用。
2)request_region(int io_port, int off_set,char *devname)
如果這段I/O埠沒有被佔用,在我們的驅動程序中就可以使用它。在使用之前,必須向系統登記,以防止被其他程序佔用。登記後,在/proc/ioports文件中可以看到你登記的I/O口。
參數1:io埠的基地址。
參數2:io埠佔用的范圍。
參數3:使用這段io地址的設備名。
在對I/O口登記後,就可以放心地用inb(), outb()之類的函來訪問了。
在一些pci設備中,I/O埠被映射到一段內存中去,要訪問這些埠就相當於訪問一段內存。經常性的,我們要獲得一塊內存的物理地址。

2。內存操作
在設備驅動程序中動態開辟內存,不是用malloc,而是kmalloc,或者用get_free_pages直接申請頁。釋放內存用的是kfree,或free_pages。 請注意,kmalloc等函數返回的是物理地址!
注意,kmalloc最大隻能開辟128k-16,16個位元組是被頁描述符結構佔用了。
內存映射的I/O口,寄存器或者是硬體設備的RAM(如顯存)一般佔用F0000000以上的地址空間。在驅動程序中不能直接訪問,要通過kernel函數vremap獲得重新映射以後的地址。
另外,很多硬體需要一塊比較大的連續內存用作DMA傳送。這塊程序需要一直駐留在內存,不能被交換到文件中去。但是kmalloc最多隻能開辟128k的內存。
這可以通過犧牲一些系統內存的方法來解決。

3。中斷處理
同處理I/O埠一樣,要使用一個中斷,必須先向系統登記。
int request_irq(unsigned int irq ,void(*handle)(int,void *,struct pt_regs *),
unsigned int long flags, const char *device);
irq: 是要申請的中斷。
handle:中斷處理函數指針。
flags:SA_INTERRUPT 請求一個快速中斷,0 正常中斷。
device:設備名。

如果登記成功,返回0,這時在/proc/interrupts文件中可以看你請求的中斷。
4。一些常見的問題。
對硬體操作,有時時序很重要(關於時序的具體問題就要參考具體的設備晶元手冊啦!比如網卡晶元RTL8139)。但是如果用C語言寫一些低級的硬體操作的話,gcc往往會對你的程序進行優化,這樣時序會發生錯誤。如果用匯編寫呢,gcc同樣會對匯編代碼進行優化,除非用volatile關鍵字修飾。最保險的辦法是禁止優化。這當然只能對一部分你自己編寫的代碼。如果對所有的代碼都不優化,你會發現驅動程序根本無法裝載。這是因為在編譯驅動程序時要用到gcc的一些擴展特性,而這些擴展特性必須在加了優化選項之後才能體現出來。
寫在後面:學習Linux確實不是一件容易的事情,因為要付出很多精力,也必須具備很好的C語言基礎;但是,學習Linux也是一件非常有趣的事情,它裡麵包含了許多高手的智慧和「幽默」,這些都需要自己親自動手才能體會到,O(∩_∩)O~哈哈!

⑶ Linux驅動的軟體架構

Linux不是為了某單一電路板而設計的操作系統,它可以支持約30種體系結構下一定數量的硬體,因此,它的驅動架構很顯然不能像RTOS下或者無操作系統下那麼小兒科的做法。Linux設備驅動非常重視軟體的可重用和跨平台能力。譬如,如果我們寫下一個DM9000網卡的驅動,Linux的想法是這個驅動應該最好一行都不要改就可以在任何一個平台上跑起來。
#ifdef BOARD_Xxx
#define DM9000_BASE 0x100oo#define DM900o_IRQ 8
#elif defined(BOARD_YYY)#define DM9000_BASEox200oo#define DM90oo_IRo 7
#elif defined (BOARD_Z2Z)#define DM9000_BASEox3000o#define DM9o0o_IRQ9...
#endif
上述代碼主要有如下問題:
1)此段代碼看起來面目可憎,如果有100個板子,就要iflelse 100次,到了第101個板子,又得重新加ifelse。代碼進行著簡單的「復制—粘貼」,「復制—粘貼」式的簡單重復通常意味著代碼編寫者的水平很差。
2)非常難做到一個驅動支持多個設備,如果某個電路板上有兩個DM9000網卡,則DM9000_BASE這個宏就不夠用了,此時勢必要定義出來DM9000_BASE 1、DM9000_BASE 2、DM9000_IRQ 1、DM9000_IRQ 2類的宏;定義了DM9000_BASE 1、DM9000_BASE2後,如果又有第3個DM9000網卡加到板子上,前面的代碼就又不適用了。
3)依賴於make menuconfig選擇的項目來編譯內核,因此,在不同的硬體平台下要依賴於所選擇的BOARD_XXX、BOARD_YYY選項來決定代碼邏輯。這不符合ARM Linux 3.x一個映像適用於多個硬體的目標。實際上,我們可能同時選擇了BOARD_XXX、BOARD_YYY、BOARD_ZZZ。
我們按照上面的方法編寫代碼的時候,相信自己編著編著也會覺得奇怪,代碼不好。這個時候,我們有沒有辦法把設備端的信息從驅動裡面剝離出來,讓驅動以某種標准方法拿到這些平台信息呢Linux匯流排、設備和驅動模型實際上可以做到這一點,驅動就可以放之四海而皆準了。

⑷ linux主機側與設備側USB驅動

USB採用樹形拓撲結構,主機側和設備側的USB控制器分別稱為主機控制器((Host Controller)和USB設備控制器(UDC),每條匯流排上只有一個主機控制器,負責協調主機和設備間的通信,而設備不能主動向主機發送任何消息。

在Linux系統中,USB驅動可以從兩個角度去觀察,一個角度是主機側,一個角度是設備側。從上圖主機側去看,在Linux驅動中,處於USB驅動最底層的是USB主機控制器硬體,在其上運行的是USB主機控制器驅動,在主機控制器上的為USB核心層,再上層為USB設備驅動層(插入主機上的U盤、滑鼠、USB轉串口等設備驅動)。因此,在主機側的層次結構中,要實現的USB驅動包括兩類:USB主機控制器驅動和USB設備驅動,前者控制插入其中的USB設備,後者控制USB設備如何與主機通信。Linux內核中的USB核心負責USB驅動管理和協議處理的主要工作。主機控制器驅動和設備驅動之間的USB核心非常重要,其功能包括:通過定義一些數據結構、宏和功能函數,向上為設備驅動提供編程介面,向下為USB主機控制器驅動提供編程介面;維護整個系統的USB設備信息;完成設備熱插拔控制、匯流排數據傳輸控制等。

⑸ linux驅動程序如何調用

1、進入到Ubuntu桌面後,打開終端,快捷鍵為ctrl+alt+T。

注意事項:

在很多企業網路中,為了追求速度和安全,Linux操作系統不僅僅是被網路運維人員當作伺服器使用,Linux既可以當作伺服器,又可以當作網路防火牆是Linux的 一大亮點。

⑹ linux如何安裝驅動

在Intel網站直接下載的Linux驅動是e1000-5.2.52.tar.gz(版本可能會有改變),這個壓縮包裡面沒有編譯好的.o的文件,需要在Linux系統下編譯之後才能使用,
因為網卡需要編譯,所以要先確認將內核源文件安裝好,下面是關於內核源文件的安裝
● Linux下添加內核源文件
1. 用rpm –qa|grep kernel-source查看是否安裝了這個包;
如果返回結果中有kernel-source-xxx(其中xxx為當前redhat的內核版本,如rhel3為2.4.21-4EL), 即已經 安裝。如無返回結果則需要安裝kernel-source包。到安裝光碟中找到kernel-source-xxx.i386.rpm,用下面命令安裝此rpm包:
2.如果安裝了用rpm -V kernel-source校驗是否有文件丟失,如果沒有輸出,表示文件完整;
3.如果有丟失用rpm -ivh --force kernel-source-xxxx...把包重新安裝一下;
這個kernel-source包,在您的RH安裝光碟中,在Redhat/RPMS中,如果以前沒有安裝過這個包,那麼用rpm -ivh kernel-source-xxxx...來安裝,如果安裝過,需要覆蓋安裝,使用rpm -ivh --force kernel-source-xxxx...這個命令強制安裝。
註:AS 4 開始,沒有kernel-source這個包了,取而代之的是kernel-dev這個包,檢查這個包有沒有安裝的方法同上
● 驅動安裝步驟:
1. 把這個tar文件拷貝到用戶自己定義的目錄中,例如:
/home/username/e1000 or /usr/local/src/e1000
2. 用tar命令解這個壓縮包:
tar zxf e1000-5.2.52.tar.gz
3. 切換到驅動的src目錄下:
cd e1000-5.2.52/src/
4. 編譯這個驅動模塊:
make
然後安裝這個模塊
make install
這個二進制元將被安裝到如下位置:
/lib/moles//kernel/drivers/net/e1000.o
以上的路徑是默認的安裝位置,在某些linux版本中可能是其他位置,具體信息可以查看在驅動的 tar壓縮包中的ldistrib.txt文件.
5. 安裝模塊:
insmod e1000 (2.6以上的版本最好使用全路徑安裝 P insmod /lib/moles//kernel/drivers/net/e1000/e1000.ko)
6. 設定網卡IP地址:
ifconfig ethx <IP_address> x是網卡介面的號
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
若多個網卡的晶元相同可以cp ifcfg-eth0 ifcfg-eth1~~~~~~
修改下裡面的drive名稱就OK
!!!!!!!!!!!!!!!!!!!
在網卡的編譯中很可能不能進行下去~這個原因除了kernel的開發包沒有安裝外還可能是由於開發環境不完全所引起的!
這時就需要你講開發環境安裝完成,最簡單的辦法就是通過 sysconfig-config-packet 安裝gcc
安裝完成後繼續執行 make ;make install

了解更多開源相關,去LUPA社區看看吧

⑺ 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操作系統下,載入驅動的方式有二:
靜態載入驅動;
動態載入驅動;

作為前者,靜態載入驅動是通過將驅動程序編譯到內核而進行的一系列配置操作;對於後者而言則是向內核注冊設備信息,從而在kernel啟動後,再通過insmod指令,關聯好主、次設備號,從而以模塊的形式進行載入的;

二者各有優點,所以應用的場合也是不一樣的;

⑼ 想學習Linux 驅動,需要什麼知識

首先,接觸linux操作系統,在你的電腦上裝一個linxu操作系統(建議ubuntu,比
較友好),熟悉經常要用的命令,熟悉環境(建議看「鳥哥的linux私房菜」)。
其次,閱讀經典書籍是不可少的,建議先看ldd前四章,大概了解linux驅動的框架
,驅動是做什麼的,該如何寫驅動,那本書上有一些例子,可以在你的電腦上編譯
,執行看看。後面的章節在結合自己的情況而定。
第三,建議閱讀ulk(understanding the linux kernel)所有的內容,了解linux
內核的一些基本知識,在心中建立一個框架,不必完全懂,深入了解就好,以後經
常翻翻,受益無窮!
第四,別著急,這才是你真的進入linux驅動的第一步,花點錢買個開發板吧,然
後了解代碼的編譯,下載,看看板子的datasheet,針對自己感興趣的深入研究。
建議學習流程,led燈控制---tp---i2c匯流排-----lcd-----camera----flash----
wifi/bt等。因為這個裡面牽涉了甚多內核的子系統(input,v4l2,fb等
),所以可能要多話時間看代碼,了解代碼的框架,設計的思想等,只要一步一個
腳印,一定會有所成。
第五,因為現在的移動設備大多數都是android的了,所以你就要看看linux
kernel在android的作用,然後往上看看,看看hal層的代碼,這些在調試中都是需
要的,如果有興趣,更加可以看看framework的代碼了,學習android一些工作機制
,類似於surfaceflinger,audioflinger等等。。
《linux就該這么學》免費提供最新Linux技術教程書籍,為開源技術愛好者努力做
得更多更好

⑽ Linux字元設備驅動的組成

在Linux中,字元設備驅動由如下幾個部分組成。
1.字元設備驅動模塊載入與卸載函數
在字元設備驅動模塊載入函數中應該實現設備號的申請和cdev的注冊,而在卸載函數中應實現設備號
的釋放和cdev的注銷。
Linux內核的編碼習慣是為設備定義一個設備相關的結構體,該結構體包含設備所涉及的cdev、私有
數據及鎖等信息。2.字元設備驅動的file_operations結構體中的成員函數
file_operations結構體中的成員函數是字元設備驅動與內核虛擬文件系統的介面,是用戶空間對Linux
進行系統調用最終的落實者。設備驅動的讀函數中,filp是文件結構體指針,buf是用戶空間內存的地址,該地址在內核空間不宜直
接讀寫,count是要讀的位元組數,f_pos是讀的位置相對於文件開頭的偏移。
設備驅動的寫函數中,filp是文件結構體指針,buf是用戶空間內存的地址,該地址在內核空間不宜直
接讀寫,count是要寫的位元組數,f_pos是寫的位置相對於文件開頭的偏移。
由於用戶空間不能直接訪問內核空間的內存,因此藉助了函數_from_user()完成用戶空間緩沖
區到內核空間的復制,以及_to_user()完成內核空間到用戶空間緩沖區的復制,見代碼第6行和第14
行。
完成內核空間和用戶空間內存復制的_from_user()和_to_user()的原型分別為:
unsigned long _from_user(void *to, const void _ _user *from, unsigned long count);
unsigned long _to_user(void _ _user *to, const void *from, unsigned long count);
上述函數均返回不能被復制的位元組數,因此,如果完全復製成功,返回值為0。如果復制失敗,則返
回負值。如果要復制的內存是簡單類型,如char、int、long等,則可以使用簡單的put_user()和
get_user()讀和寫函數中的_user是一個宏,表明其後的指針指向用戶空間,實際上更多地充當了代碼自注釋的
功能。內核空間雖然可以訪問用戶空間的緩沖區,但是在訪問之前,一般需要先檢查其合法性,通過
access_ok(type,addr,size)進行判斷,以確定傳入的緩沖區的確屬於用戶空間。

閱讀全文

與linuxqudong相關的資料

熱點內容
皓強工具解壓步驟 瀏覽:688
部隊抗洪搶險命令範文 瀏覽:886
歐姆龍plc編程軟體使用教程 瀏覽:592
ai文件pdf 瀏覽:911
騰訊雲伺服器掛載混合雲 瀏覽:758
智能小車用什麼單片機 瀏覽:463
java怎麼給窗口關閉 瀏覽:940
列舉51單片機的定址方式 瀏覽:706
剪輯app怎麼寫長篇文字 瀏覽:400
app專屬流量過月租怎麼不更新 瀏覽:654
王者程序員都有誰 瀏覽:76
給牛換腳掌解壓 瀏覽:387
圍棋有多少種演算法 瀏覽:602
unity資源包在哪個文件夾 瀏覽:704
阿里雲伺服器遠程鏈接不成功 瀏覽:482
文件系統pdf 瀏覽:767
原神安卓區服什麼意思 瀏覽:37
貝殼app怎麼線上發布 瀏覽:161
如何挑選安卓系統機頂盒 瀏覽:55
安卓快充使用有什麼注意事項 瀏覽:911