核心版本: 2.4.22
閱讀此文的目的: 學會編寫linux裝置驅動。
閱讀此文的方法: 閱讀以下2個檔案: hello.c,asdf.c。
此文假設讀者:
已經能用c語言編寫linux應用程式,
理解"字元裝置檔案, 塊裝置檔案, 主裝置號, 次裝置號",
會寫簡單的shell指令碼和makefile。
1. "hello.c"
--------------------------------
/* * 這是我們的第乙個原始檔,
* 它是乙個可以載入的核心模組,
* 載入時顯示"hello,world!",
* 解除安裝時顯示"bye!"。
* 需要說明一點,寫核心或核心模組不能用寫應用程式時的系統呼叫或函式庫,
* 因為我們寫的就是為應用程式提供系統呼叫的**。
* 核心有專用的函式庫,如, , 等,
* 現在還沒必要了解得很詳細,
* 這裡用到的printk的功能類似於printf。
* "/usr/src/linux"是你實際的核心原始碼目錄的乙個符號鏈結,
* 如果沒有現在就建立乙個,因為下面和以後都會用到。
* 編譯它用"gcc -c -i/usr/src/linux/include hello.c",
* 如果正常會生成檔案hello.o,
* 載入它用"in**od hello.o",
* 只有在文字終端下才能看到輸出。
* 解除安裝它用"rmmod hello"
*/ /*
* 小技巧: 在使用者目錄的.bashrc裡加上一行:
* alias mkmod='gcc -c -i/usr/src/linux/include'
* 然後重新登陸shell,
* 以後就可以用"mkmod hello.c"的方式來編譯核心模組了。
*/ /* 開始例行公事 */
#ifndef __kernel__
# define __kernel__
#endif
#ifndef module
# define module
#endif
#include
#include
module_license("gpl");
#ifdef config_**p
#define __**p__
#endif
/* 結束例行公事 */
#include /* printk()在這個檔案裡 */
static int
init_module
() static void
cleanup_module
() ------------------------------------
2. "asdf.c"
------------------------------------
/* * 這個檔案是乙個核心模組。
* 核心模組的編譯,載入和解除安裝在前面已經介紹了。
* 這個模組的功能是,建立乙個字元裝置。
* 這個裝置是一塊4096位元組的共享記憶體。
* 核心分配的主裝置號會在載入模組時顯示。
*/ /* 開始例行公事 */
#ifndef __kernel__
# define __kernel__
#endif
#ifndef module
# define module
#endif
#include
#include
#ifdef config_**p
#define __**p__
#endif
module_license("gpl");
/* 結束例行公事 */
#include /* copy_to_user(), copy_from_user */
#include /* struct file_operations, register_chrdev(), ... */
#include /* printk()在這個檔案裡 */
#include /* 和任務排程有關 */
#include /* u8, u16, u32 ... */
/* * 關於核心功能庫,可以去網上搜尋詳細資料,
*/ /* 檔案被操作時的**功能 */
static int asdf_open (struct inode *inode, struct file *filp);
static int asdf_release (struct inode *inode, struct file *filp);
static ssize_t asdf_read (struct file *filp, char *buf, size_t count,loff_t *f_pos);
static ssize_t asdf_write (struct file *filp, const char *buf, size_t count,loff_t *f_pos);
static loff_t asdf_lseek (struct file * file, loff_t offset, int orig);
/* 申請主裝置號時用的結構, 在linux/fs.h裡定義 */
struct file_operations asdf_fops = ;
static int asdf_major; /* 用來儲存申請到的主裝置號 */
static u8 asdf_body[4096]="asdf_body/n"; /* 裝置 */
static int
init_module
() static void
cleanup_module
() /*
* 編譯這個模組然後載入它,
* 如果正常,會顯示你的裝置的主裝置號。
* 現在你的裝置就建立好了,我們可以測試一下。
* 假設你的模組申請到的主裝置號是254,
* 執行"mknod abc c 254 0",就建立了我們的裝置檔案abc。
* 可以把它當成乙個4096位元組的記憶體塊來測試一下,
* 比如"cat abc", "cp abc image", "cp image abc",
* 或寫幾個應用程式用它來進行通訊。
* 介紹一下兩個需要注意的事,
* 一是printk()的顯示只有在非圖形模式的終端下才能看到,
* 二是載入過的模組最好在不用以後解除安裝掉。
* 如果對linux環境的系統呼叫很陌生,建議先看apue這本書。
*/ static int
asdf_open /* open** */
( struct inode *inode,
struct file *filp
) static int
asdf_release /* close** */
( struct inode *inode,
struct file *filp
) static ssize_t
asdf_read /* read** */
( struct file *filp,
char *buf,
size_t count,
loff_t *f_pos
) if (copy_to_user(buf, asdf_body+*f_pos, count)) return -efault; /* 把資料寫到應用程式空間 */
*f_pos = pos; /* 改變檔案的讀寫位置 */
return count; /* 返回讀到的位元組數 */
} static ssize_t
asdf_write /* write**,和read一一對應 */
( struct file *filp,
const char *buf,
size_t count,
loff_t *f_pos
) if (copy_from_user(asdf_body+*f_pos, buf, count)) return -efault;
*f_pos = pos;
return count;
} static loff_t
asdf_lseek /* lseek** */
( struct file * file,
loff_t offset,
int orig
) if ((pos>4096) || (pos<0))
return file->f_pos = pos;
}
linux驅動編寫(usb host驅動入門)
usb協議是乙個複雜的協議,目前涉及到的版本就有usb1.0,usb2.0,usb3.0。大家如果開啟kernel usb host目錄,就會發現下面包含了ohci,uhci,ehci,xhci,whci等多種形式的控制器驅動。那麼,對於我們這些不是很了解usb的開發人員,如何了解usb的 結構呢?...
linux驅動入門實驗
帥得不敢出門 c 愛好者灌水天堂 3503799 由於沒有開發板,只好做pc機下linux的模組載入了.原理與開發板的是一樣的.編寫dri arh.c源 然後編譯,我就不寫makefile了 直接命令編譯它 root localhost 0430 gcc d kernel dmodule wall ...
linux驅動之入門
首先通過第乙個程式簡單了解下驅動的框架 首先 開發環境 fedora 17 核心版本 3.9.10 檢視核心版本命令 uname r 更新核心命令 yum update 需重啟之後檢視核心才行 另外需要安裝編譯好的核心的標頭檔案和庫 yum install kernel devel arm開發板型號...