新聞中心
深入淺出:Linux字符設(shè)備號(hào)解析

發(fā)展壯大離不開廣大客戶長(zhǎng)期以來(lái)的信賴與支持,我們將始終秉承“誠(chéng)信為本、服務(wù)至上”的服務(wù)理念,堅(jiān)持“二合一”的優(yōu)良服務(wù)模式,真誠(chéng)服務(wù)每家企業(yè),認(rèn)真做好每個(gè)細(xì)節(jié),不斷完善自我,成就企業(yè),實(shí)現(xiàn)共贏。行業(yè)涉及封陽(yáng)臺(tái)等,在網(wǎng)站建設(shè)、成都全網(wǎng)營(yíng)銷推廣、WAP手機(jī)網(wǎng)站、VI設(shè)計(jì)、軟件開發(fā)等項(xiàng)目上具有豐富的設(shè)計(jì)經(jīng)驗(yàn)。
在Linux系統(tǒng)中,設(shè)備文件可分為兩種類型:塊設(shè)備和字符設(shè)備。其中字符設(shè)備,是一種能夠一次性讀寫一個(gè)字節(jié)或一個(gè)字符的設(shè)備,如鍵盤、鼠標(biāo)、打印機(jī)、聲卡等。而字符設(shè)備號(hào),則用于在Linux系統(tǒng)中唯一標(biāo)識(shí)每個(gè)字符設(shè)備。本篇文章將深入淺出地解析Linux字符設(shè)備號(hào)的相關(guān)知識(shí)。
Linux字符設(shè)備號(hào)的定義
在Linux系統(tǒng)中,每個(gè)字符設(shè)備號(hào)由兩部分組成:主設(shè)備號(hào)和次設(shè)備號(hào)。主設(shè)備號(hào)用于標(biāo)識(shí)設(shè)備所屬的設(shè)備類型,同時(shí)也決定了字符設(shè)備的主要操作函數(shù);而次設(shè)備號(hào)則用于標(biāo)識(shí)同一類型設(shè)備的不同實(shí)例。
一般情況下,主設(shè)備號(hào)的值是預(yù)設(shè)的,而次設(shè)備號(hào)則由內(nèi)核動(dòng)態(tài)分配。在Linux源碼的include/linux/major.h中,我們可以找到一些已經(jīng)預(yù)設(shè)好的主設(shè)備號(hào),如下所示:
“`
#define MEM_MAJOR 1
#define FLOPPY_MAJOR 2
#define HD_MAJOR 3
#define TTY_MAJOR 4
#define LP_MAJOR 6
“`
其中,4號(hào)主設(shè)備號(hào)的被稱為tty設(shè)備,即終端設(shè)備,這是Linux中最常見的設(shè)備類型。其他設(shè)備類型如網(wǎng)絡(luò)設(shè)備、聲卡、輸入設(shè)備等,都有自己的主設(shè)備號(hào)。
次設(shè)備號(hào)的分配
Linux內(nèi)核用一套動(dòng)態(tài)分配的方式來(lái)為字符設(shè)備分配次設(shè)備號(hào)。這一套機(jī)制叫做udev(user space device),是內(nèi)核態(tài)和用戶態(tài)之間交互的重要組成部分。
當(dāng)我們插入一臺(tái)新設(shè)備時(shí),udev會(huì)首先查詢目錄/lib/udev/devices,找到一個(gè)未使用的次設(shè)備號(hào),然后創(chuàng)建一個(gè)對(duì)應(yīng)的設(shè)備文件,最終將該設(shè)備文件與對(duì)應(yīng)的次設(shè)備號(hào)關(guān)聯(lián)。這樣,在用戶態(tài)通過(guò)設(shè)備文件訪問(wèn)到設(shè)備時(shí),實(shí)際上是通過(guò)該文件與次設(shè)備號(hào)關(guān)聯(lián)起來(lái)的。
此外,次設(shè)備號(hào)的分配方式還可以通過(guò)內(nèi)核態(tài)ioctl接口進(jìn)行配置。在實(shí)際開發(fā)中,我們可以通過(guò)下面這段代碼來(lái)修改設(shè)備的次設(shè)備號(hào)
“`
int ioctl(int fd, unsigned long cmd, unsigned long arg);
“`
其中fd是打開設(shè)備文件返回的文件描述符,cmd是需要執(zhí)行的命令,arg是與命令有關(guān)的參數(shù)。通過(guò)這個(gè)接口,我們可以動(dòng)態(tài)分配和修改次設(shè)備號(hào),實(shí)現(xiàn)更精細(xì)的設(shè)備管理和控制。
Linux字符設(shè)備號(hào)的使用
有了主次設(shè)備號(hào),我們就可以構(gòu)造字符設(shè)備號(hào)了。在Linux內(nèi)核的include/linux/fs.h中,有一個(gè)宏MKDEV,可以用于將主次設(shè)備號(hào)合并成一個(gè)字符設(shè)備號(hào)。例如:
“`
dev_t devno = MKDEV(2, 1); // devno此時(shí)為 0x0201
“`
其中,2表示主設(shè)備號(hào),1表示次設(shè)備號(hào)。需要注意的是,主次設(shè)備號(hào)的更大取值都為255,在分配前需要充分考慮到主設(shè)備號(hào)的預(yù)設(shè)值。
除了MKDEV宏,我們還可以通過(guò)字符設(shè)備相關(guān)頭文件的宏定義來(lái)獲取主設(shè)備號(hào)或次設(shè)備號(hào)。
其中,MAJOR宏返回設(shè)備號(hào)的主設(shè)備號(hào),MINOR宏返回設(shè)備號(hào)的次設(shè)備號(hào)。我們也可以用來(lái)這樣直接獲取設(shè)備號(hào)
“`
dev_t devno;
devno = inode->i_rdev; // 獲取設(shè)備號(hào)
unsigned int major = MAJOR(devno);
unsigned int minor = MINOR(devno);
“`
其中,inode是一個(gè)Linux內(nèi)核中的數(shù)據(jù)結(jié)構(gòu),表示一個(gè)文件的i-node節(jié)點(diǎn)。通過(guò)i-node節(jié)點(diǎn),我們可以訪問(wèn)到文件的各項(xiàng)屬性,包括文件所關(guān)聯(lián)的設(shè)備文件。i_rdev即是i-node節(jié)點(diǎn)中的設(shè)備號(hào)信息。
在Linux系統(tǒng)中,字符設(shè)備是一種能夠一次性讀寫一個(gè)字節(jié)或一個(gè)字符的設(shè)備,如鍵盤、鼠標(biāo)、打印機(jī)、聲卡等。字符設(shè)備號(hào)則用于在Linux系統(tǒng)中唯一標(biāo)識(shí)每個(gè)字符設(shè)備。
字符設(shè)備號(hào)由兩部分組成:主設(shè)備號(hào)和次設(shè)備號(hào)。其中,主設(shè)備號(hào)用于標(biāo)識(shí)設(shè)備所屬的設(shè)備類型,次設(shè)備號(hào)則用于標(biāo)識(shí)同一類型設(shè)備的不同實(shí)例。主設(shè)備號(hào)的值是預(yù)設(shè)的,而次設(shè)備號(hào)則由內(nèi)核動(dòng)態(tài)分配。
通過(guò)MKDEV宏、MAJOR宏和MINOR宏等宏定義,我們可以方便地獲取和操作字符設(shè)備號(hào)。同時(shí),通過(guò)ioctl接口,我們還可以動(dòng)態(tài)分配和修改次設(shè)備號(hào),實(shí)現(xiàn)更精細(xì)的設(shè)備管理和控制。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
在Linux內(nèi)核中,注冊(cè)字符設(shè)備驅(qū)動(dòng)程序的函數(shù)是?
字符設(shè)備驅(qū)動(dòng)程序框架 1、寫出open、write函數(shù) 2、告訴內(nèi)核 1)、定義一個(gè)struct file_operations結(jié)構(gòu)并填充好 static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* 這是一個(gè)宏,推向編譯模塊時(shí)自動(dòng)創(chuàng)建的__this_module變量 */ .open = first_drv_open, .write = first_drv_write, }; 2)、把struct file_operations結(jié)構(gòu)體告訴內(nèi)核 major = register_chrdev(0, “first_drv”, &first_drv_fops); // 注冊(cè), 告訴內(nèi)核相關(guān)參數(shù):之一個(gè),設(shè)備號(hào),0自動(dòng)分配主設(shè)備號(hào),否則為主設(shè)備號(hào)0-255 第二個(gè):設(shè)備名第二個(gè):struct file_operations結(jié)構(gòu)體 4)、register_chrdev由誰(shuí)調(diào)用(入口函數(shù)調(diào)用) static int first_drv_init(void) 5)、入口函數(shù)須使用內(nèi)核宏來(lái)修飾 module_init(first_drv_init); module_init會(huì)定義一個(gè)結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體里面有一個(gè)函數(shù)指針指向first_drv_init這個(gè)函數(shù),當(dāng)我們加載或安裝一個(gè)驅(qū)動(dòng)時(shí),內(nèi)核會(huì)自動(dòng)找到這個(gè)結(jié)構(gòu)體,然后調(diào)用里面的函數(shù)指針,這個(gè)函數(shù)指針指向first_drv_init這個(gè)函數(shù),first_drv_init這個(gè)函數(shù)就是把struct file_operations結(jié)構(gòu)體告訴內(nèi)核 6)、有入口函數(shù)就有出口函數(shù) module_exit(first_drv_exit); 最后加上協(xié)議 MODULE_LICENSE(“GPL”); 3、mdev根據(jù)系統(tǒng)信息自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn): 每次寫驅(qū)動(dòng)都要手動(dòng)創(chuàng)建設(shè)備文件過(guò)于麻煩,使用設(shè)備管理文件系統(tǒng)則方便很多。在2.6的內(nèi)核以前一直使用的是devfs,但是它存在許多缺陷。它創(chuàng)建了大量的設(shè)備文件,其實(shí)這些設(shè)備更本不存在。而且設(shè)備與設(shè)備文件的映射具有不確定性,比如U盤即可能對(duì)應(yīng)sda,又可能對(duì)應(yīng)sdb。沒(méi)有足夠的主/輔設(shè)備號(hào)。2.6之后的內(nèi)核引入了sysfs文件系統(tǒng),它掛載在/sys上,配合udev使用,可以很好的完成devfs的功能,并彌補(bǔ)了那些缺點(diǎn)。(這里說(shuō)一下,當(dāng)今內(nèi)核已經(jīng)使用netlink了)。 udev是用戶空間的一個(gè)應(yīng)用程序,在嵌入式中用的是mdev,mdev在busybox中。mdev是udev的精簡(jiǎn)版。首先在busybox中添加支持mdev的選項(xiàng): Linux System Utilities —> mdev Support /etc/mdev.conf Support subdirs/symlinks Support regular expressions substitutions when renaming device Support command execution at device addition/removal 然后修改/etc/init.d/rcS: echo /in/mdev > /proc/sys/kernel/hotplug /in/mdev -s 執(zhí)行mdev -s :以‘-s’為參數(shù)調(diào)用位于 /in目錄寫的mdev(其實(shí)是個(gè)鏈接,作用是傳遞參數(shù)給/bin目錄下的busybox程序并調(diào)用它),mdev掃描 /sys/class 和 /sys/block 中所有的類設(shè)備目錄,如果在目錄中含有名為“dev”的文件,且文件中包含的是設(shè)備號(hào),則mdev就利用這些信息為這個(gè)設(shè)備在/dev 下創(chuàng)建設(shè)備節(jié)點(diǎn)文件。一般只在啟動(dòng)時(shí)才執(zhí)行一次 “mdev -s”。熱插拔事件:由于啟動(dòng)時(shí)運(yùn)行了命 令:echo /in/mdev > /proc/sys/kernel/hotplug ,那么當(dāng)有熱插拔事件產(chǎn)生時(shí),內(nèi)核就會(huì)調(diào)用位于 /in目錄的mdev。這時(shí)mdev通過(guò)環(huán)境變量中的 ACTION 和 DEVPATH,來(lái)確定此次熱插拔事件的動(dòng)作以及影響了/sys中的那個(gè)目錄。接著會(huì)看看這個(gè)目錄中是否“dev”的屬性文件,如果有就利用這些信息為 這個(gè)設(shè)備在/dev 下創(chuàng)建設(shè)備節(jié)點(diǎn)文件重新打包文件系統(tǒng),這樣/sys目錄,/dev目錄就有東西了下面是create_class的原型: #define class_create(owner, name) / ({ / static struct lock_class_key __key; / __class_create(owner, name, &__key); / }) extern struct class * __must_check __class_create(struct module *owner, const char *name, struct lock_class_key *key); class_destroy的原型如下: extern void class_destroy(struct class *cls); device_create的原型如下: extern struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, …) __attribute__((format(printf, 5, 6))); device_destroy的原型如下: extern void device_destroy(struct class *cls, dev_t devt); 具體使用如下,可參考后面的實(shí)例: static struct class *firstdrv_class; static struct class_device *firstdrv_class_dev; firstdrv_class = class_create(THIS_MODULE, “firstdrv”); firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, “xyz”); /* /dev/xyz */ class_device_unregister(firstdrv_class_dev); class_destroy(firstdrv_class); 下面再來(lái)看一下應(yīng)用程序如何找到這個(gè)結(jié)構(gòu)體的在應(yīng)用程序中我們使用open打開一個(gè)設(shè)備:如:open(/dev/xxx, O_RDWR); xxx有一個(gè)屬性,如字符設(shè)備為c,后面為讀寫權(quán)限,還有主設(shè)備名、次設(shè)備名,我們注冊(cè)時(shí) 通過(guò)register_chrdev(0, “first_drv”, &first_drv_fops)(有主設(shè)備號(hào),設(shè)備名,struct file_operations結(jié)構(gòu)體)將first_drv_fops結(jié)構(gòu)體注冊(cè)到內(nèi)核數(shù)組chrdev中去的,結(jié)構(gòu)體中有open,write函數(shù),那么應(yīng)用程序如何找到它的,事實(shí)上是根據(jù)打開的這個(gè)文件的屬性中的設(shè)備類型及主設(shè)備號(hào)在內(nèi)核數(shù)組chrdev里面找到我們注冊(cè)的first_drv_fops,實(shí)例代碼: #include #include #include #include #include #include #include #include #include #include static struct class *firstdrv_class; static struct class_device *firstdrv_class_dev; volatile unsigned long *gpfcon = NULL; volatile unsigned long *gpfdat = NULL; static int first_drv_open(struct inode *inode, struct file *file) { //printk(“first_drv_open\n”); /* 配置GPF4,5,6為輸出 */ *gpfcon &= ~((0x3); return 0; } if (strcmp(argv, “on”) == 0) { val = 1; } else { val = 0; } write(fd, &val, 4); return 0; }
Linux驅(qū)動(dòng)與設(shè)備節(jié)點(diǎn)簡(jiǎn)介 & Android內(nèi)核與Linux內(nèi)核的區(qū)別
驅(qū)動(dòng)是內(nèi)核的一部分,作為直接訪問(wèn)物理硬件的一個(gè)軟件層,用于應(yīng)用程序與物理硬件設(shè)備通信。內(nèi)核包含多種驅(qū)動(dòng),如WIFI、USB、Audio、藍(lán)牙、相機(jī)、顯示驅(qū)動(dòng)。
(1)設(shè)備驅(qū)動(dòng)程序三類:字符設(shè)備驅(qū)動(dòng)程序、塊設(shè)備驅(qū)動(dòng)程序、網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序;
(2)對(duì)應(yīng)Linux三類設(shè)備:字符設(shè)備、塊設(shè)備、網(wǎng)絡(luò)設(shè)備;
(3)常見字符設(shè)備:鼠標(biāo)、鍵盤、串口、控制臺(tái)等;
(4)常見塊設(shè)備:各種硬盤、flash磁盤、RAM磁盤等;
(5)網(wǎng)絡(luò)設(shè)備(網(wǎng)絡(luò)接口):eth0、eth1,注:網(wǎng)絡(luò)設(shè)備沒(méi)有設(shè)備節(jié)點(diǎn),應(yīng)用程序通過(guò)Socket訪問(wèn)網(wǎng)絡(luò)設(shè)備。由于網(wǎng)絡(luò)設(shè)備面向報(bào)文,較難實(shí)現(xiàn)相關(guān)read、write等文件讀寫函數(shù),所以驅(qū)動(dòng)的實(shí)現(xiàn)也與字符設(shè)備和塊設(shè)備不同。
Linux使用對(duì)文件一樣的管理方式來(lái)管理設(shè)備,所有設(shè)備都以文件的形式存放在/dev目錄下,系統(tǒng)中的每個(gè)字符設(shè)備或者塊設(shè)備都必須為其創(chuàng)建一個(gè)設(shè)備文件,它包含了該設(shè)備的設(shè)備類型(塊設(shè)備或字符設(shè)備)、設(shè)備號(hào)(主設(shè)備號(hào)和次設(shè)備號(hào))以及設(shè)備訪問(wèn)控制屬性等。設(shè)備節(jié)點(diǎn)通過(guò)
mknod
命令創(chuàng)建,也可以由Udev用戶工具軟件在系統(tǒng)啟動(dòng)后根據(jù)/sys目錄下每個(gè)設(shè)備的實(shí)際信息創(chuàng)建,使用后一種方式可以為每個(gè)設(shè)備動(dòng)態(tài)分配設(shè)備號(hào)。
Linux中設(shè)備節(jié)點(diǎn)通過(guò)“mknod”命令創(chuàng)建,創(chuàng)建時(shí)需要指定主設(shè)備號(hào)和次設(shè)備號(hào),即指定對(duì)應(yīng)的驅(qū)動(dòng)程序和對(duì)應(yīng)的物理設(shè)備(訪問(wèn)設(shè)備節(jié)點(diǎn)時(shí)就相當(dāng)于通過(guò)其設(shè)備號(hào)訪問(wèn)驅(qū)動(dòng)程序進(jìn)而間接訪問(wèn)到物理設(shè)備)。主設(shè)備號(hào)用來(lái)區(qū)分不同種類的設(shè)備,而次設(shè)備號(hào)用來(lái)區(qū)分同一類型的多個(gè)設(shè)備。對(duì)于常用設(shè)備,Linux有約定俗成的編號(hào),如硬盤的主設(shè)備號(hào)是3
理解:應(yīng)用程序通過(guò)訪問(wèn)設(shè)備節(jié)點(diǎn)讀取主設(shè)備號(hào)和次設(shè)備號(hào),通過(guò)主設(shè)備號(hào)找對(duì)應(yīng)的驅(qū)動(dòng),通過(guò)次設(shè)備號(hào)對(duì)應(yīng)到具體物理設(shè)備。注:1個(gè)驅(qū)動(dòng)對(duì)應(yīng)一類設(shè)備,并用唯一主設(shè)備號(hào)標(biāo)識(shí)。
Linux支持的各種設(shè)備的主設(shè)備號(hào)定義在include/linux/major.h文件中,已經(jīng)在官方注冊(cè)的主設(shè)備號(hào)和次設(shè)備號(hào)在Documentation/devices.txt文件中。
Android系統(tǒng)更底層是Linux,并且在中間加上了一個(gè)Dalvik / ART的Java虛擬機(jī),從表面層看是Android運(yùn)行庫(kù)。每個(gè)Android應(yīng)用都運(yùn)行在自己的進(jìn)程上,享有Dalvik / ART虛擬機(jī)為它分配的專有實(shí)例,并支持多個(gè)虛擬機(jī)在同一設(shè)備上高效運(yùn)行,虛擬機(jī)執(zhí)行的是專有格式的可執(zhí)行文件(.dex) – 該格式經(jīng)過(guò)優(yōu)化,以將內(nèi)存好用降到更低。
Android內(nèi)核和Linux內(nèi)核的差別主要體現(xiàn)在如下11個(gè)方面:
關(guān)于linux 字符設(shè)備號(hào)的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
創(chuàng)新互聯(lián)-老牌IDC、云計(jì)算及IT信息化服務(wù)領(lǐng)域的服務(wù)供應(yīng)商,業(yè)務(wù)涵蓋IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)服務(wù)、云計(jì)算服務(wù)、IT信息化、AI算力租賃平臺(tái)(智算云),軟件開發(fā),網(wǎng)站建設(shè),咨詢熱線:028-86922220
網(wǎng)站名稱:「深入淺出:Linux字符設(shè)備號(hào)解析」(linux字符設(shè)備號(hào))
URL鏈接:http://fisionsoft.com.cn/article/dhcicie.html


咨詢
建站咨詢
