999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

Linux核心定制在嵌入式系統中應用的探討

2013-06-25 08:45:14陳剛
中國信息化·學術版 2013年3期
關鍵詞:嵌入式設備

陳剛

【中圖分類號】TP316 【文獻標識碼】A 【文章編號】1672-5158(2013)03-0086-03

隨著硬件的發展,只靠匯編語言已經無法滿足嵌入式系統的開發要求了;同時種類繁多的開發平臺無論是硬件的還是軟件的平臺都讓人難以挑選;但是可以看到的是一些專用的軟件平臺必將被歷史淘汰;硬件上ARM在嵌入式系統一家獨大的局面也必將被打破。INTER也即將發布手機用CPU,AMD已經推出移動和嵌入式設備用的三個系列CPU;所以源代碼開放對各種硬件支持良好的LINUX是嵌入式系統開發的必選軟件平臺;但是由于LINUX是針對臺式機筆記本的,所以在各式驅動和內存等的支持上的過多導致相對嵌入式系統來說過分龐大;所以在嵌入式系統的開發中,我們可以對LINUX內核的驅動模塊和內存管理上進行刪減和定制;(Android系統、虛擬操作系統VMware的最新版本等都是對LINUX內核的驅動和內存管理進行深層次定制修改的LINUX變種)本文主要討論在LINUX內核中定制開發嵌入式系統的驅動。

對linux的devfs類型的驅動程序的編寫可以從以下幾大內容理解和入手:

通過分析驅動程序源代碼可以發現驅動程序一般可分三部分:

核心數據結構;核心數據和資源的初始化,注冊以及注消,釋放;底層設備操作函數;

A.核心數據結構

struct file_operations fops 設備驅動程序接口struct file_operations { struct module *owner;

loff_t (*llseek) (struct file *,loff_t,int);

ssize_t (*read) (struct file *,char *,size_t,loff_t *);

ssize_t (*write) (struct file *,const char *,size_t,loff_t *); int (*readdir) (struct file *,void *,filldir_t);

unsigned int (*poll) (struct file *,struct poll_table_struct *);

int (*ioctl) (struct inode *,struct file *,unsigned int,unsigned long);

int (*mmap) (struct file *,struct vm_area_struct *);

int (*open) (struct inode *,struct file *);

int (*flush) (struct file *);

int (*release) (struct inode *,struct file *);

int (*fsync) (struct file *,struct dentry *,int datasync); int (*fasync) (int,struct file *,int);

int (*lock) (struct file *,int,struct file_lock *);

ssize_t (*readv) (struct file *,const struct iovec *,unsigned long,loff_t*);

ssize_t (*writev) (struct file *,const struct iovec *,unsigned long,loff_t *);

ssize_t (*sendpage) (struct file *,struct page *,int,size_t,loff_t *,int);

unsigned long (*get_unmapped_area)(struct file *,unsigned long,unsigned long,unsigned long,unsigned long);

};

block_device_operations 塊設備驅動程序接口{ int (*open) (struct inode *,struct file *); int (*release) (struct inode *,struct file *);

int (*ioctl) (struct inode *,struct file *,unsigned,unsigned long);

int (*check_media_change) (kdev_t);

int (*revalidate) (kdev_t);

struct module *owner;

};塊設備的READ().WRITE()不在這里注冊,而是在設備的讀寫請求隊列里注冊,內核在這里將調用通用的blk_read(),blk_write().向讀寫隊列

發出讀寫請求.

Linux 利用這些數據結構向內核注冊open(),release(),ioctl(),check_ media_change(),rvalidate()等函數的入口句柄.

我們將要編寫的open(),release(),ioctl(),check_media_change(),Revali date()等函數,將在驅動初始化的時候,

通過一個此結構類型的變量向內核提供函數的 入口.

struct request_queue_t 設備請求隊列的數據結構

struct request_list {

unsigned int count;

unsigned int pending[2];

struct list_head free;

};

struct request {

struct list_head queue;

int elevator_sequence;

kdev_t rq_dev;

int cmd; /* READ or WRITE */

int errors;

unsigned long start_time;

unsigned long sector;

unsigned long nr_sectors;

unsigned long hard_sector,hard_nr_sectors;

unsigned int nr_segments;

unsigned int nr_hw_segments;

unsigned long current_nr_sectors,hard_cur_sectors;

void * special;

char * buffer;

struct completion * waiting;

struct buffer_head * bh;

struct buffer_head * bhtail;

request_queue_t *q;

};

struct request_queue

{

/*

* the queue request freelist,one for reads and one for writes*/

struct request_list rq;

/*

* The total number of requests on each queue

*/

int nr_requests;

/*

* Batching threshold for sleep/wakeup decisions

*/

int batch_requests;

/*

* The total number of 512byte blocks on each queue

*/

atomic_t nr_sectors;

/*

* Batching threshold for sleep/wakeup decisions

*/

int batch_sectors;

/*

* The max number of 512byte blocks on each queue

*/

int max_queue_sectors;

/*

* Together with queue_head for cacheline sharing

*/

struct list_head queue_head;

elevator_t elevator;

request_fn_proc * request_fn;

merge_request_fn * back_merge_fn;

merge_request_fn * front_merge_fn;

merge_requests_fn * merge_requests_fn;

make_request_fn * make_request_fn;

plug_device_fn * plug_device_fn;

/*

* The queue owner gets to use this for whatever they like.

* ll_rw_blk doesnt touch it.

*/

void * queuedata;

/*

* This is used to remove the plug when tq_disk runs.

*/

struct tq_struct plug_tq;

/*

* Boolean that indicates whether this queue is plugged or not.

*/

int plugged:1;

/*

* Boolean that indicates whether current_request is active or

* not.

*/

int head_active:1;

/*

* Boolean that indicates you will use blk_started_sectors

* and blk_finished_sectors in addition to blk_started_io

* and blk_finished_io. It enables the throttling code to

* help keep the sectors in flight to a reasonable value

*/

int can_throttle:1;

unsigned long bounce_pfn;

/*

* Is meant to protect the queue in the future instead of

* io_request_lock

*/

spinlock_t queue_lock;

/*

* Tasks wait here for free read and write requests

*/

wait_queue_head_t wait_for_requests;

struct request *last_request;

};

緩沖區和對緩沖區相應的I/O操作在此任務隊列中相關聯,等待內核的調度.如果是字符設備就不需要此數據結構.而

塊設備的read(),write()函數則在buffer_queue的initize和設備請求隊列進行處理請求時候傳遞給request_fn().

struct request_queue_t{}設備請求隊列的變量類型,驅動程序在初始化的時候需要填寫request_fn().

其他的數據結構還有 I/O port,Irq,DMA 資源分配,符合POSIX標準的ioctl的cmd的構造和定義,以及描述設備自身的

相關數據結構定義-如設備的控制寄存器的相關數據結構定義,BIOS里的參數定義,設備類型定義等.

B.初始化和注冊和注消,模塊方式驅動程序的加載和卸載.

設備驅動程序在定義了數據結構后,首先開始初始化:

如I/O 端口的檢查和登記,內核對 I/O PORT的檢查和登記提供了兩個 函數check_region(int io_port,int off_set)

和request_region(int io_port,int off_set,char *devname).I/O Port登記后,就可以用inb()和outb()進行操作了 .

還有DMA和Irq的初始化檢查和 登記,

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文件中可以看你請求的中斷。

DMA主要是在內存中分配交換內存空間.還有緩沖區,設備請求隊列的初始化.

還有設備控制寄存器的檢查和初始化,還有對設備自身相關的數據結構的初始化,填寫一些設備特定的數據等.

然后,開始注冊

devfs_register()向VFS注冊統一的設備操作函數.

static struct file_operations XXX_fops = {

owner: THIS_MODULE, XXX_fops所屬的設備模塊

read: XXX_read, 讀設備操作

write: XXX_write, 寫設備操作

ioctl: XXX_ioctl, 控制設備操作

mmap: XXX_mmap, 內存重映射操作

open: XXX_open, 打開設備操作

release: XXX_release 釋放設備操作

/* ... */

};

blk_init_queue()隊列初始化函數.

request_irq()中斷注冊函數

相應的注消函數:

devfs_unregister (devfs_handle_t de){};

free_irq()釋放中斷,I/O資源,釋放緩沖區,釋放設備,請求隊列,VFS節點等.

模塊方式驅動程序的加載和卸載.

static int __init _init_module (void)

{

/* ... */

}

static void __exit _cleanup_module (void)

{

}

/* 加載驅動程序模塊入口 */

module_init(_init_module);

/* 卸載驅動程序模塊入口 */

module_exit(_cleanup_module);

_intrrupt()

設備發生中斷時的處理程序.

{

1.對共享中斷的處理;

2.對spinlock以及其他的事務的處理;

}

C. 底層設備操作函數的編寫

read().write(),open(),release(),check_media_change(),revalidate()等.

open()和release()

打開設備是通過調用file_operations結構中的函數open( )來完成的,它是驅動程序用來為今后的操作完成初始化準備工作的。在大部分驅動程序中,open( )通常需要完成下列工作:

1. 檢查設備相關錯誤,如設備尚未準備好等。

2. 如果是第一次打開,則初始化硬件設備。

3. 識別次設備號,如果有必要則更新讀寫操作的當前位置指針

f_ops。

4. 分配和填寫要放在file->private_data里的數據結構。

5. 使用計數增1。

釋放設備是通過調用file_operations結構中的函數release( )來完成的,這個設備方法有時也被稱為close( ),它的作用正好與open( )相反,通常要完成下列工作:

1. 使用計數減1。

2. 釋放在file->private_data中分配的內存。

3. 如果使用計算為0,則關閉設備。

read()和 write()

字符設備的讀寫操作相對比較簡單,直接使用函數read( )和write( )就可以了。但如果是塊設備的話,則需要調用函數block_read( )和block_write( )來進行數據讀寫,這兩個函數將向設備請求表中增加讀寫請求,以便Linux內核可以對請求順序進行優化。由于是對內存緩沖區而不是直接對設備進行操作的,因此能很大程度上加快讀寫速度。如果內存緩沖區中沒有所要讀入的數據,或者需要執行寫操作將數據寫入設備,那么就要執行真正的數據傳輸,這是通過調用數據結構blk_dev_struct中的函數request_fn( )來完成的。

ioctl()--將cmd進行解釋,并送到設備的控制寄存器.事實上,read()和write()也要通過ioctl()來完成操作的 .

ioctl(){

CASE CMD{

SWITCH CASE1:{...};

SWITCH CASE2:{...};

SWITCH CASE N:{...};

.

.

DEFAULT : {...};

}

END CASE

總結:

我們可以看出一個linux的驅動程序通常包含如下:

初始化設備模塊、

{I/O port,DMA.Irq,內存 buffer,初始化并且填寫具體設備數據結構,注冊 fops的具體函數等等 }

中斷處理模塊、設備釋放模塊、設備卸載模塊

設備打開模塊、數據讀寫和控制模塊、

驅動裝載模塊、驅動釋放模塊.

猜你喜歡
嵌入式設備
諧響應分析在設備減振中的應用
TS系列紅外傳感器在嵌入式控制系統中的應用
電子制作(2019年7期)2019-04-25 13:17:14
基于VB6.0+Access2010開發的設備管理信息系統
嵌入式系統通信技術的應用
電子制作(2018年18期)2018-11-14 01:48:16
基于MPU6050簡單控制設備
電子制作(2018年11期)2018-08-04 03:26:08
搭建基于Qt的嵌入式開發平臺
嵌入式軟PLC在電鍍生產流程控制系統中的應用
電鍍與環保(2016年3期)2017-01-20 08:15:32
500kV輸變電設備運行維護探討
工業設計(2016年12期)2016-04-16 02:52:00
如何在設備采購中節省成本
原來他們都是可穿戴設備
消費者報道(2014年7期)2014-07-31 11:23:57
主站蜘蛛池模板: 67194亚洲无码| 亚洲日本韩在线观看| 无码在线激情片| 日韩在线成年视频人网站观看| 国产XXXX做受性欧美88| 亚洲成a人片7777| 亚洲精品无码在线播放网站| 国产欧美视频在线观看| 亚洲国产看片基地久久1024| 日韩黄色在线| 国产午夜人做人免费视频中文| 四虎永久在线| Jizz国产色系免费| 人妻中文字幕无码久久一区| 嫩草国产在线| 美女无遮挡被啪啪到高潮免费| 黄色网站在线观看无码| 亚洲色无码专线精品观看| 欧美三级不卡在线观看视频| 精品无码一区二区三区在线视频| 国产成人综合在线观看| 国内黄色精品| 亚洲第一中文字幕| 天堂成人在线| 成人小视频网| 都市激情亚洲综合久久| 黄色片中文字幕| 国产特级毛片| 国产日韩欧美中文| 中国成人在线视频| 午夜少妇精品视频小电影| 91精品免费高清在线| 欧美精品亚洲日韩a| 欧美日韩另类在线| 国产精品女熟高潮视频| 亚洲一区二区三区在线视频| 欧美一级99在线观看国产| 综合人妻久久一区二区精品 | 一本大道香蕉高清久久| 亚洲视频免费在线看| 欧美在线国产| 亚洲精选无码久久久| 亚洲精品老司机| 国产成在线观看免费视频| 亚洲性影院| 国产精品手机视频一区二区| 国产午夜人做人免费视频中文| 综合网久久| 欧美.成人.综合在线| 成人午夜免费观看| 玖玖精品视频在线观看| 免费在线国产一区二区三区精品| 成人自拍视频在线观看| 黄网站欧美内射| 欧洲日本亚洲中文字幕| 亚洲av日韩av制服丝袜| 91在线一9|永久视频在线| 97视频在线精品国自产拍| 青青草原国产一区二区| 亚洲日韩第九十九页| 精品久久久久久成人AV| 国产乱肥老妇精品视频| 亚洲综合九九| 免费亚洲成人| 亚洲国产在一区二区三区| 国产成人毛片| 日韩av手机在线| 国产成+人+综合+亚洲欧美| 午夜国产精品视频| 国产精品微拍| 精品人妻一区无码视频| 激情无码视频在线看| 国产成人高清亚洲一区久久| 国产一级片网址| 看av免费毛片手机播放| 成人在线亚洲| 国产亚洲欧美在线中文bt天堂| 国产超薄肉色丝袜网站| 国产一级在线观看www色| 久久精品波多野结衣| 欧美一区二区丝袜高跟鞋| 中文字幕在线看|