Linux驅動入門

2021-04-12 23:55:05 字數 4421 閱讀 1334

核心版本: 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開發板型號...