1.mystery引入
1)裝置驅動程式對外提供如下的功能:
1)裝置初始化:對硬體裝置進行初始化操作
2)資料交換:資料交換包括由核心層向硬體層傳送資料、從硬體層讀取資料到核心層;
應用程式向裝置檔案傳送資料、裝置檔案向應用程式回送資料
3)裝置請求與檢測:檢測各硬體裝置的各種參數資訊、錯誤資訊
4)裝置釋放:裝置使用完後的資源釋放
2)驅動一般分為字元裝置驅動、塊裝置驅動和網絡裝置驅動
1)字元裝置驅動:可以按位元組操作的方式對裝置檔案進行存取,一般對應慢速裝置,例如序列槽裝置
2)塊裝置驅動:是按資料塊的方式對裝置檔案進行通路,一般對應高速裝置,例如DMA
3)網絡裝置驅動:是面向網卡裝置,用于處理網絡封包的發送與接收
3)字元裝置與塊裝置均可以通過通路檔案的方式進行操作,二者唯一的不同的是Linux對于它們的資料管理方式的不同。
4)應用程式對字元裝置的I/O操作,會直接傳送到核心驅動層,而塊裝置的操作,則是需要借助于中間的緩存區,以間接的方式進行資料交換。
2.環境搭建及測試
1)下載下傳對應版本的核心源碼包
2)因為現在對核心還不是很熟,加上核心源碼比較大,是以我先下一個核心的開發包
3)終端:
sudo yum install kernel-devel
4)如圖
5)環境搭建好了,問題又來了。。uname -r 的結果和我系統核心版本不一樣。。
這裡我直接用我系統的核心版本号作測試了,我的系統核心版本是3.6.10-2.fc17.i686
6)第一個版本的Makefile檔案如下:
obj-m:=chardev.o
KDIR:=/lib/modules/3.6.10-2.fc17.i686/build
SRCPWD:=$(shell pwd)
all:
make -C $(KDIR) M=$(SRCPWD) modules
clean:
rm -rf chardev.o
7)編譯結果如圖
3.驅動驗證
1)裝置安裝
當安裝驅動時,又出現錯誤了,糾結。。錯誤:編譯使用的核心和目前系統的核心不一樣!
2)反思
1)這時我才想起,前斷時間我更新了下系統,當時把系統核心更新到了3.6,但是無法進入系統,是以我直接把grub項的3.6核心的引導删掉了,現在打開grub查找錯誤
2)grub中關于核心3.6開機引導項内容如下:
3)看了這斷代碼,對更新後新核心無法進入系統的原因就明了了,我在想,為什麼更新核心的時候沒有制作initrd
4)于是我退後一步,自己制作initrd,終端下:
mkinitrd initrd-3.6.6 3.6.6
(先切換到linux-3.6.6的上一級目錄),由于系統更新核心時已經編譯過核心鏡像和核心子產品了,并且也已經安裝過核心子產品了
5)是以我要做的就是将initrd複制到boot目錄下,然後再添加新的引導項
6)在上圖 echo 'Loading Fedora (3.6.10-2.fc17.i686)' 的下一行添加自己制作的initrd,代碼:initrd/boot/initrd-3.6.10-2.fc17.i686.img
7)重新開機電腦,OK,成功引導進行新核心,但是有很多地方不盡人意
1)電腦需要重裝顯示卡驅動,分辨率太低
2)無法聯網,需要重裝網卡驅動
3)無法挂載FAT格式的盤
4)無法挂載NTFS格式的盤
8)是以,我還是決定用3.3的核心,隻是在3.6下作驅動程式測試
4.驅動測試
1)如圖所示:
2)驅動裝置建立好後,編寫一個程式驗證下
3)效果如圖:
4)這裡出現OPEN錯誤和READ錯誤,但是卻又讀出了驅動函數的内容,表示驅動還是成功的,由于這個核心開始出現的不盡人意,也沒有去調試這個錯誤的原因
5.驅動源代碼
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
static int char_read(struct file *filp,char __user *buffer,size_t,loff_t *);
static int char_open(struct inode *,struct file *);
static int char_write(struct file *filp,const char __user *buffer,size_t ,loff_t*);
static int char_release(struct inode *,struct file *);
static int device_open_count;
static int major;
static const struct file_operations file_ops =
{
.read = char_read,
.write = char_write,
.open = char_open,
.release = char_release,
};
static int __init char_init(void)
{
int value;
major = 0;
value = register_chrdev(major, "chardev", &file_ops);
if (value < 0)
{
printk("無法注冊裝置");
return value;
}
if (major == 0)
major = value;
return 0;
}
static int char_open(struct inode *inode,struct file *file)
{
if(device_open_count == 0)
device_open_count++;
else
{
printk("裝置已經被打開\n");
return -1;
}
try_module_get(THIS_MODULE);
return 0;
}
static int char_release(struct inode *inode,struct file *file)
{
device_open_count--;
module_put(THIS_MODULE);
return 0;
}
static int char_read(struct file *filp,char __user *buffer,size_t length,loff_t *offset)
{
if(length < 0)
return -1;
else if(length > 12)
length = 12;
if(copy_to_user(buffer,"Hello Linux!",length))
return length;
return -1;
}
static int char_write(struct file *filp,const char __user *buffer,size_t length,loff_t *offset)
{
return 0;
}
static void __exit module_close(void)
{
unregister_chrdev(major, "chardev");
}
module_init(char_init);
module_exit(module_close);
6.Makefile源代碼
obj-m:=chardev.o
KDIR:=/lib/modules/$(shell uname -r)/build
SRCPWD:=$(shell pwd)
all:
make -C $(KDIR) M=$(SRCPWD) modules
clean:
rm -rf chardev.o
7.測試程式源代碼
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(void)
{
int testdev;
int i,rf=0;
char buf[15];
memset(buf, 0, sizeof(buf));
testdev = open("/dev/chardev",O_RDWR);
if ( testdev == -1 )
{
perror("open\n");
exit(0);
}
rf=read(testdev,buf,11);
if(rf<0)
perror("read error\n");
printf("R:%s\n",buf);
close(testdev);
return 0;
}
本文出自 “成鵬緻遠” 部落格,請務必保留此出處http://infohacker.blog.51cto.com/6751239/1155153
QQ聯系方式:[email protected]
出處:lcw.cnblogs.com
本文申明:本文版權歸作者和部落格園共有,歡迎轉載,轉載請注明出處.