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
主站蜘蛛池模板: 欧美怡红院视频一区二区三区| 亚洲成aⅴ人片在线影院八| 久久大香香蕉国产免费网站| 国产欧美视频在线| 91视频99| 在线毛片网站| 国产va在线观看免费| 五月婷婷综合色| 88国产经典欧美一区二区三区| 国产亚洲视频中文字幕视频| 亚洲国产综合第一精品小说| 久久精品日日躁夜夜躁欧美| 高清视频一区| 中文字幕一区二区人妻电影| 91欧美亚洲国产五月天| 99久久99这里只有免费的精品| 亚洲国产成人在线| 永久在线精品免费视频观看| 91免费精品国偷自产在线在线| 视频二区亚洲精品| 国产精品网曝门免费视频| 国产福利免费在线观看| 国产欧美网站| 日本一区二区三区精品视频| 97久久超碰极品视觉盛宴| 日韩欧美网址| 久久综合九色综合97婷婷| 国产视频自拍一区| 久久夜色撩人精品国产| m男亚洲一区中文字幕| 成人国产精品视频频| 国产高潮视频在线观看| 国产精品内射视频| 中文字幕欧美成人免费| 亚洲伊人久久精品影院| 国产精品制服| 99久久国产自偷自偷免费一区| 久热99这里只有精品视频6| 日韩精品一区二区三区中文无码| 91精品aⅴ无码中文字字幕蜜桃| 一级毛片免费观看不卡视频| 91亚洲免费| 欧美视频在线观看第一页| 91精品人妻一区二区| 97se综合| 日韩一区二区三免费高清| 女人av社区男人的天堂| 成人一区在线| 红杏AV在线无码| 国产美女91视频| 国产熟女一级毛片| 国产成人1024精品| 台湾AV国片精品女同性| 最新日本中文字幕| 久操中文在线| 日韩国产 在线| 欧美a级在线| 九色综合视频网| 99国产精品免费观看视频| 亚洲最大福利视频网| 免费jizz在线播放| 波多野结衣一区二区三区AV| 中日韩欧亚无码视频| 狠狠色丁香婷婷| 亚洲有无码中文网| 国产成人久久综合一区| 一本一道波多野结衣一区二区| 亚洲无码四虎黄色网站| 高清精品美女在线播放| 黄色网站在线观看无码| 久久激情影院| 亚洲精品综合一二三区在线| 人妻少妇乱子伦精品无码专区毛片| 亚洲三级网站| 国产97区一区二区三区无码| 成年人视频一区二区| 国产永久免费视频m3u8| 欧美性久久久久| 91麻豆精品国产91久久久久| 精品91视频| 香蕉色综合| 精品视频免费在线|