終於。。。
我開始寫部落格了。。。。。
因為懶。。。所以拖了很久。。。。。
以後要多堅持。。。。。。。。。
今天主要是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排程 請求佇列...