色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > Linux設備驅(qū)動申請設備號過程分析

Linux設備驅(qū)動申請設備號過程分析 時間:2017-11-22      來源:未知

今天我們通過內(nèi)核中的源碼共同分析一下Linux設備驅(qū)動中申請設備號的過程,首先在Linux內(nèi)核為我們提供了兩種申請設備號的方式,一是指定設備號注冊,二是動態(tài)分配設備號;分別用到一下兩個函數(shù):

register_chrdev_region();

alloc_chrdev_region();

設備號的數(shù)據(jù)類型是dev_t類型,是一個無符號長整型,在32位操作系統(tǒng)中,它的大小是4個字節(jié),32位,高12位用來存放主設備號,低20位用來存放次設備號。

通過主設備號和次設備號合成設備號的宏如下:

MKDEV(major,minor);

從設備號中提取主設備號和次設備號的宏如下:

MAJOR(dev);

MINOR(dev);

接下來我們就來分析設備號注冊過程:

一、自動分配設備號:

1.  調(diào)用內(nèi)核提供的自動分配設備號函數(shù),分配設備號 

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)  

2. alloc_chrdev_region函數(shù)中繼續(xù)調(diào)用如下函數(shù),進行進一步申請 

struct char_device_struct *cd =  __register_chrdev_region(0, baseminor, count, name);

/*在該函數(shù)中進行判斷,如果major==0,執(zhí)行if內(nèi)的語句*/

if (major == 0) {                     //自動分配時major == 0

/*

*chrdevs是一個結(jié)構(gòu)體指針數(shù)組,見附錄1-1

*作用是從struct char_device_struct類型的結(jié)構(gòu)體指針數(shù)組中找到一個空的結(jié)構(gòu)體指針

*/

for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {  // for(i=254;i>0;i--)

if (chrdevs[i] == NULL)

break;

}

if (i == 0) {      //i == 0 ,說明,存放設備號的結(jié)構(gòu)體指針數(shù)組已經(jīng)用完

ret = -EBUSY;

goto out;

}

major = i;         //否則,主設備號 = i

ret = major;

cd->major = major;                       // 將主設備號賦值給cd->major

cd->baseminor = baseminor;       // 將起始次設備號賦值cd->baseminor

cd->minorct = minorct;    // 將傳入的第三個參數(shù)賦值給程cd->minorct,

                                                     // 表示申請設備號的個數(shù)

strlcpy(cd->name, name, sizeof(cd->name));  //設備名拷貝

/*

*struct char_device_struct *cd, **cp;

*cp存放的是結(jié)構(gòu)體指針的地址,基于當前的條件,*cp == NULL ,所以for循環(huán)條件不成立

*/

--------------------------------------不執(zhí)行-------------------------------------

for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)          

if ((*cp)->major > major ||((*cp)->major == major &&(((*cp)->baseminor >= baseminor) ||((*cp)->baseminor + (*cp)->minorct > baseminor))))

break;

---------------------------------------------------------------------------------------

/*     **cp == NULL ,所以條件不成立*/

---------------------------------------不執(zhí)行-----------------------------------------

if (*cp && (*cp)->major == major) {

int old_min = (*cp)->baseminor;

int old_max = (*cp)->baseminor + (*cp)->minorct - 1;

int new_min = baseminor;

int new_max = baseminor + minorct - 1;

/* New driver overlaps from the left.  */

if (new_max >= old_min && new_max <= old_max) {

ret = -EBUSY;

goto out;

}

/* New driver overlaps from the right.  */

if (new_min <= old_max && new_min >= old_min) {

ret = -EBUSY;

goto out;

}

}

---------------------------------------------------------------------------------------

cd->next = *cp;                  //cd ->next = NULL

*cp = cd;  //*cp[chrdevs[i]] , cd 結(jié)構(gòu)體在上面賦值的

mutex_unlock(&chrdevs_lock);

return cd;

回到alloc_chrdev_region函數(shù)的*dev = MKDEV(cd->major, cd->baseminor);

實際上就申請了一個主設備號,次設備號

二、用戶指定設備號注冊(eg:major = 250;count=3)

1. int register_chrdev_region(dev_t from, unsigned count, const char *name);

2. 在該函數(shù)中進行如下操作:

dev_t to = from + count;      // dev_t to =  MKDEV(dev_major,dev_minor) +3;

dev_t n, next;

/*如果申請的設備編號范圍跨越了主設備號,

*它會把分配范圍內(nèi)的編號按主設備號分割

 *成較小的子范圍,并在每個子范圍上調(diào)用

 *__register_chrdev_region() 。如果其中

*有一次分配失敗的話,那會把之前成功分配的都全部退回*/

// for(n = MKDEV(dev_major,dev_minor); n<to;n=next)循環(huán)一次(next = to)

for (n = from; n < to; n = next) {

next = MKDEV(MAJOR(n)+1, 0);         // next = MKDEV(250+1,0);

if (next > to)                       // if(MKDEV(251,0)>MKDEV(250,0)+3) [成立]

next = to;                          // next = MKDEV(250,0)+3

cd = __register_chrdev_region(MAJOR(n), MINOR(n),next - n, name);

//__register_chrdev_region(250, 0,3, "xxx_demo");

      {

 cd->major = major;           //cd->major = 250;

cd->baseminor = baseminor;   //cd->baseminor = 0;

cd->minorct = minorct;           //cd->minorct  = 3;

strlcpy(cd->name, name, sizeof(cd->name));

i = major_to_index(major);   //i = 250;

/*for (cp = &chrdevs[250]; *cp; cp = &(*cp)->next)*/

for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)        

if((*cp)->major > major || ((*cp)->major == major &&(((*cp)->baseminor >= baseminor) ||((*cp)->baseminor + (*cp)->minorct > baseminor))))    //正常情況下不會成立,即次設備號范圍不會重復

break;

 

/*判斷次設備號范圍是否重復,如果重復就錯誤返回*/

if (*cp && (*cp)->major == major) {

int old_min = (*cp)->baseminor;

int old_max = (*cp)->baseminor + (*cp)->minorct - 1;

int new_min = baseminor;

int new_max = baseminor + minorct - 1;

/* New driver overlaps from the left.  */

if (new_max >= old_min && new_max <= old_max) {

ret = -EBUSY;

goto out;

}

/* New driver overlaps from the right.  */

if (new_min <= old_max && new_min >= old_min) {

ret = -EBUSY;

goto out;

}

}

/*將設備號的結(jié)構(gòu)體插入到散列表中*/

 cd->next = *cp

 *cp = cd;

 }

附錄1-1:

 

#define CHRDEV_MAJOR_HASH_SIZE 255

static struct char_device_struct {

struct char_device_struct *next;

unsigned int major;

unsigned int baseminor;

int minorct;

char name[64];

struct cdev *cdev; /* will die */

} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];

附錄1-2

上一篇:ARM處理器異常處理

下一篇:linux內(nèi)核時間管理

熱點文章推薦
華清學員就業(yè)榜單
高薪學員經(jīng)驗分享
熱點新聞推薦
前臺專線:010-82525158 企業(yè)培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權(quán)所有 ,京ICP備16055225號-5京公海網(wǎng)安備11010802025203號

回到頂部

色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区
主站蜘蛛池模板: 欧美日韩国产在线播放| 色哟哟网站入口亚洲精品| 国产亚洲一区二区在线| 另类图片亚洲另类| 国产精品99久久久久久久久久久久| 亚洲自拍中文字幕| 精品少妇一区二区30p| 国产精品一区二区性色av | 国产欧美日韩精品专区| 亚洲一区二区久久| 欧美中文在线免费| 中文字幕日韩av综合精品| 青草成人免费视频| 色吧影院999| 国产精品视频自在线| 久久久精品美女| 91天堂在线观看| 欧美国产在线视频| 亚洲欧洲国产一区| 青青久久av北条麻妃海外网| 中文字幕久热精品视频在线| 国产精品久久久久久久电影| 久久夜色精品国产亚洲aⅴ| 国产一区二中文字幕在线看 | 久久精品国产99国产精品澳门| 日韩av免费看| 欧美日本亚洲视频| 亚洲精品福利免费在线观看| 欧美激情va永久在线播放| 久久综合色影院| 中文字幕亚洲一区| www.xxxx欧美| 欧美一级大胆视频| 国内精品模特av私拍在线观看| 国产在线拍偷自揄拍精品| 日本亚洲欧洲色α| 欧美—级高清免费播放| 亚洲精品久久久一区二区三区 | 5278欧美一区二区三区| 黑人巨大精品欧美一区二区一视频 | 欧美成人性生活|