linux字元裝置完全分析(一)

2021-08-13 21:34:12 字數 2993 閱讀 7561

終於。。。

我開始寫部落格了。。。。。

因為懶。。。所以拖了很久。。。。。

以後要多堅持。。。。。。。。。

今天主要是linux 字元裝置分析,既然是分析,那就要往深了分析才有意思。。

字元裝置的表示當然是指這個struct cdev結構。let us see。。。

struct cdev ;
kobj用來表示sys下的目錄,owner模組使用者指標,一般賦值為this_module,第三個引數很關鍵file_operations,是使用者層呼叫open、release、write、read函式時。傳到核心層處理,第四個結構list表示的是乙個鍊錶節點。第五個是裝置號,沒什麼講的。第六個是count

怎麼分配結構體cdev呢,有兩種方式,一種是靜態定義乙個 struct cdev my_cdev,然後在使用cdev_init函式去初始化該結構,第二種方式是利用cdev_alloc函式去動態申請。

有的人會先使用cdev_alloc函式去動態分配,在使用函式cdev_init去初始化,其實這種用法是不太正確的,為什麼呢?且看下面分析。

void cdev_init(struct cdev *cdev, const

struct file_operations *fops)

struct cdev *cdev_alloc(void)

return p;

}

看出相同之處和不同之處了嗎,yes kobject_init這個函式是關鍵,關鍵在於ktype型別不同、

static

struct kobj_type ktype_cdev_default = ;

static

struct kobj_type ktype_cdev_dynamic = ;

很明顯,再看

static

void cdev_default_release(struct kobject *kobj)

static

void cdev_dynamic_release(struct kobject *kobj)

對,多了乙個kfree,也就是說alloc申請出來的cdev占用的記憶體空間可以在裝置被解除安裝時自動釋放。

下面來看linux 核心怎麼管理字元裝置號。

核心提供了兩種方式,一種是alloc_chrdev_region另乙個是register_chrdev_region,兩個的底層實現如出一轍。下面來分析alloc_chrdev_region。

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,

const char *name)

主要的函式是__register_chrdev_region(0, baseminor, count, name);

static

struct char_device_struct *

__register_chrdev_region(unsigned int major, unsigned int baseminor,

int minorct, const

char *name)

if (i == 0)

major = i;

ret = major;

}cd->major = major;

cd->baseminor = baseminor;

cd->minorct = minorct;

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

i = major_to_index(major);

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)

/* new driver overlaps from the right. */

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

}cd->next = *cp;//掛接到雜湊表裡面

*cp = cd;

mutex_unlock(&chrdevs_lock);

return cd;

out:

mutex_unlock(&chrdevs_lock);

kfree(cd);

return err_ptr(ret);

}

分析到這裡,就該看乙個有意思的資料結構了,也就是所謂的雜湊表。

static

struct char_device_struct *chrdevs[chrdev_major_hash_size];

這就是雜湊表結構,chrdevs是乙個指標陣列,每乙個元素都儲存著乙個字元裝置,一看是static型別的,就知道這個chrdevs的每一項初始化後都為null,當乙個新的裝置來了之後通過主裝置號來掛接到相應的chrdevs裡面,主裝置號就是雜湊表的表頭,而衝突域就用next指標來掛接。比如我註冊了乙個major = 254 baseminor= 3 的乙個裝置和major = 254 baseminor= 6的乙個裝置,這時候chrdevs[254]就應該指向major= 254 baseminor= 3的char_device_struct結構然後該結構的next指標又指向 major= 254 baseminor= 6的char_device_struct結構。

linux字元裝置完全分析(二)

這裡主要分析一下cdev add函式。int cdev add struct cdev p,dev t dev,unsigned count 這個時候就有個關鍵的資料結構了,塊裝置也是這樣儲存的,這個結構就是cdev map。static struct kobj map cdev map struc...

Linux字元裝置驅動 一

inux字元裝置驅動之概述篇 一.概述 1.在linux中有一句哲學 linux下皆檔案 裝置驅動程式為應用程式遮蔽了硬體的細節,這樣在應用程式看來,硬體裝置只是乙個裝置檔案,應用程式可以像操作普通檔案一樣對硬體裝置進行操作。但是裝置檔案和普通檔案還是又差別的。那麼裝置和普通檔案之間又有什麼區分呢?...

Linux 塊裝置驅動分析(一)

linux 塊裝置驅動分析 一 linux 塊裝置驅動分析 二 linux 塊裝置驅動分析 三 塊裝置與字元裝置的不同 塊裝置是與字元裝置並列的概念,這兩類裝置在linux中驅動的結構有較大差異,總體而言,塊裝置驅動比字元裝置驅動要複雜得多,在i o操作上表現出極大的不同,緩衝 i o排程 請求佇列...