中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

貼心網(wǎng)絡(luò)推廣方法免費(fèi)的seo教程

貼心網(wǎng)絡(luò)推廣方法,免費(fèi)的seo教程,網(wǎng)架報(bào)價(jià)明細(xì)表,網(wǎng)站的交互怎么做一、Linux內(nèi)核對(duì)文件的分類(lèi) Linux的文件種類(lèi) 1、-:普通文件2、d:目錄文件3、p:管道文件4、s:本地socket文件5、l:鏈接文件6、c:字符設(shè)備7、b:塊設(shè)備 Linux內(nèi)核按驅(qū)動(dòng)程序?qū)崿F(xiàn)模型框架的不同&…

一、Linux內(nèi)核對(duì)文件的分類(lèi)

Linux的文件種類(lèi)

  • 1、-:普通文件
  • 2、d:目錄文件
  • 3、p:管道文件
  • 4、s:本地socket文件
  • 5、l:鏈接文件
  • 6、c:字符設(shè)備
  • 7、b:塊設(shè)備

Linux內(nèi)核按驅(qū)動(dòng)程序?qū)崿F(xiàn)模型框架的不同,將設(shè)備分為三類(lèi)

  • 1、字符設(shè)備:按字節(jié)流形式讀取的設(shè)備,一般情況下按順序訪問(wèn),數(shù)據(jù)量不大,一般不設(shè)緩存
  • 2、塊設(shè)備:按塊進(jìn)行讀寫(xiě)的設(shè)備,最小的塊大小為256字節(jié)(一個(gè)扇區(qū)),塊的大小必須是扇區(qū)的整數(shù)倍。Linux塊的大小一般為4096字節(jié),隨機(jī)訪問(wèn),設(shè)有緩存以提高效率
  • 3、網(wǎng)絡(luò)設(shè)備:針對(duì)網(wǎng)絡(luò)數(shù)據(jù)收發(fā)的設(shè)備

框圖

在這里插入圖片描述

二、設(shè)備號(hào)

  • 用于區(qū)分內(nèi)核中的同類(lèi)設(shè)備

內(nèi)核中用設(shè)備號(hào)來(lái)區(qū)分同類(lèi)里不同的設(shè)備,設(shè)備號(hào)是一個(gè)無(wú)符號(hào)的32位整數(shù),數(shù)據(jù)類(lèi)型為dev_t,設(shè)備號(hào)分為兩部分:

  • 1、主設(shè)備號(hào):占高12位,用來(lái)表示驅(qū)動(dòng)程序相同的一類(lèi)設(shè)備
  • 2、次設(shè)備號(hào):占低20位,用來(lái)表示被操作的具體設(shè)備

應(yīng)用程序打開(kāi)一個(gè)設(shè)備時(shí),通過(guò)設(shè)備號(hào)來(lái)查找定位內(nèi)核中管理的具體設(shè)備

MKDEV - 宏

  • 將主設(shè)備號(hào)和次設(shè)備號(hào)組合成32位的完整設(shè)備號(hào),用法:
dev_t id;
int major = 251;//主設(shè)備號(hào)
int minor = 2;//次設(shè)備號(hào)
id = MKDEV(251, 2);

MAJOR - 宏

  • 將主設(shè)備號(hào)從設(shè)備號(hào)中分離出來(lái),用法:
dev_t id = MKDEV(251, 2);
int major = MAJOR(id);

MINOR - 宏

  • 將次設(shè)備號(hào)從設(shè)備號(hào)中分離出來(lái),用法:
dev_t id = MKDEV(251, 2);
int minor = MINOR(id);

如果已知一個(gè)設(shè)備的主次設(shè)備號(hào),應(yīng)用指定好設(shè)備文件名,可以用mknod命令在/dev目錄下創(chuàng)建代表這個(gè)設(shè)備的文件,即此后應(yīng)用程序?qū)Υ宋募牟僮骶褪谴韺?duì)此設(shè)備的操作,用法:

cd /dev
mknod 設(shè)備文件名 設(shè)備種類(lèi)(c位字符設(shè)備,b為塊設(shè)備)	主設(shè)備號(hào)  次設(shè)備號(hào)

在應(yīng)用程序中如果要?jiǎng)?chuàng)建設(shè)備可以調(diào)用系統(tǒng)調(diào)用函數(shù)mknod,用法:

int mknod(const char *pathname,mode_t mode,dev_t dev);
pathname:帶路徑的設(shè)備文件名,無(wú)路徑默認(rèn)為當(dāng)前目錄,一般都創(chuàng)建在/dev下
mode:文件權(quán)限或S_IFCHR/S_IFBLK
dev:32位設(shè)備號(hào)

三申請(qǐng)和注冊(cè)設(shè)備號(hào)

字符設(shè)備驅(qū)動(dòng)的第一步是通過(guò)模塊的入口函數(shù)__init向內(nèi)核添加設(shè)備驅(qū)動(dòng)的代碼框架

  • 1、申請(qǐng)?jiān)O(shè)備號(hào)
  • 2、定義、初始化、向內(nèi)核添加代表本設(shè)備的結(jié)構(gòu)體元素
int register_chrdev_region(dev_t from, unsigned count, const char *name)
功能:手動(dòng)分配設(shè)備號(hào),先驗(yàn)證設(shè)備號(hào)是否被使用,如果沒(méi)有就申請(qǐng)?jiān)撛O(shè)備號(hào)
參數(shù):from:自己指定的設(shè)備號(hào)count:申請(qǐng)的設(shè)備數(shù)量name:/proc/devices文件中與該設(shè)備對(duì)應(yīng)的名字,方便用戶(hù)層查詢(xún)主設(shè)備號(hào)
返回值:成功為0,失敗是負(fù)數(shù),絕對(duì)值為錯(cuò)誤碼
int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count, const char *name)
功能:自動(dòng)分配設(shè)備號(hào),查詢(xún)內(nèi)核里未被占用的設(shè)備號(hào),如果找到則占用該設(shè)備號(hào)
參數(shù):dev:分配設(shè)備號(hào)成功后用來(lái)存放分配到的設(shè)備號(hào)baseminor:起始的次設(shè)備號(hào),一般為0count:申請(qǐng)?jiān)O(shè)備號(hào)的數(shù)量name:/proc/devices文件中與該設(shè)備對(duì)應(yīng)的名字,方便用戶(hù)層查詢(xún)主次設(shè)備號(hào)
返回值:成功后為0,失敗為負(fù)數(shù),絕對(duì)值為錯(cuò)誤碼
  • 成功分配后在/proc/devices可以查看到申請(qǐng)到的主設(shè)備號(hào)和設(shè)備名

  • 3、釋放設(shè)備號(hào)

void unregister_chrdev_region(dev_t from, unsigned count)
功能:釋放設(shè)備號(hào)
參數(shù):from:已經(jīng)成功分配到的設(shè)備號(hào)將被釋放count:申請(qǐng)成功的設(shè)備數(shù)量
  • 釋放后/proc/devices路徑下對(duì)應(yīng)的設(shè)備文件記錄消失

四:注冊(cè)字符設(shè)備

  • 1、字符設(shè)備結(jié)構(gòu)體
    #include <linux/cdev.h>
struct cdev
{struct kobject kobj;//表示該類(lèi)型實(shí)體是一種內(nèi)核對(duì)象(kernel object)struct module *owner;//填THIS_MODULE,表示還字符設(shè)備屬于哪個(gè)內(nèi)核模塊const struct file_operations *ops;//指向內(nèi)核空間中存放該設(shè)備的各種操作函數(shù)地址struct list_head list;//鏈表指針域dev_t dev;//設(shè)備號(hào)unsigned int count;//設(shè)備數(shù)量
};

自己定義的結(jié)構(gòu)體中必須要有一個(gè)成員為struct cdev cdev ,兩種定義方法:

  • 1、直接定義:定義結(jié)構(gòu)體全局變量

  • 2、動(dòng)態(tài)申請(qǐng):struct cdev * cdev_alloc()

  • 初始化

void cdev_init(struct cdev *cdev,const struct file_operations *fops)
功能:初始化字符設(shè)備結(jié)構(gòu)體
參數(shù):cdev:設(shè)備號(hào)fops:操作函數(shù)
  • 字符設(shè)備結(jié)構(gòu)體與設(shè)備號(hào)綁定
int cdev_add(struct cdev *p,dev_t dev,unsigned int count)
功能:將指定字符設(shè)備添加到內(nèi)核
參數(shù):p:指向被添加的設(shè)備dev:設(shè)備號(hào)count:設(shè)備數(shù)量
  • 移除字符設(shè)備
void cdev_del(struct cdev *p)
功能:從內(nèi)核中移除一個(gè)字符設(shè)備
參數(shù):p:設(shè)備號(hào)
  • 系統(tǒng)調(diào)用函數(shù)結(jié)構(gòu)體
    #include <linux/fs.h>
struct file_operations 
{struct module *owner;           //填THIS_MODULE,表示該結(jié)構(gòu)體對(duì)象從屬于哪個(gè)內(nèi)核模塊int (*open) (struct inode *, struct file *);	//打開(kāi)設(shè)備int (*release) (struct inode *, struct file *);	//關(guān)閉設(shè)備ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);	//讀設(shè)備ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);    //寫(xiě)設(shè)備loff_t (*llseek) (struct file *, loff_t, int);		//定位long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);//讀寫(xiě)設(shè)備參數(shù),讀設(shè)備狀態(tài)、控制設(shè)備unsigned int (*poll) (struct file *, struct poll_table_struct *);	//POLL機(jī)制,實(shí)現(xiàn)多路復(fù)用的支持int (*mmap) (struct file *, struct vm_area_struct *); //映射內(nèi)核空間到用戶(hù)層int (*fasync) (int, struct file *, int); //信號(hào)驅(qū)動(dòng)//......
};

該對(duì)象的函數(shù)指針成員對(duì)應(yīng)相應(yīng)的系統(tǒng)調(diào)用函數(shù),應(yīng)用層通過(guò)系統(tǒng)調(diào)用函數(shù)來(lái)間接調(diào)用這些函數(shù)指針指向的設(shè)備驅(qū)動(dòng)函數(shù)
在這里插入圖片描述
一般定義一個(gè)struct file_operations類(lèi)型的全局變量,并用自己實(shí)現(xiàn)的各種操作函數(shù)名對(duì)其初始化

總結(jié):
字符設(shè)備開(kāi)發(fā)步驟:

  • 如果設(shè)備有自己的控制數(shù)據(jù),則定義一個(gè)包含struct cdev cdev成員的結(jié)構(gòu)體(方便管理),其他成員根據(jù)設(shè)備需求。設(shè)備簡(jiǎn)單直接用struct cdev
  • 2、定義一個(gè)struct cdev的全局變量來(lái)表示該設(shè)備
  • 3、定義三個(gè)全局變量分別來(lái)表示:主設(shè)備號(hào)、次設(shè)備號(hào)、設(shè)備數(shù)量
  • 4、定義一個(gè)struct file_operations 結(jié)構(gòu)體變量,其owner成員賦值為T(mén)HIS_MODULE
  • 5、module init函數(shù)流程:a. 申請(qǐng)?jiān)O(shè)備號(hào) b. 如果是全局設(shè)備指針則動(dòng)態(tài)分配代表本設(shè)備的結(jié)構(gòu)體元素 c. 初始化struct cdev成員,設(shè)置struct cdev的owner成員為T(mén)HIS_MODULE e. 添加字符設(shè)備到內(nèi)核
  • 6、module exit函數(shù):a. 注銷(xiāo)設(shè)備號(hào) b. 從內(nèi)核中移除struct cdev. 如果如果是全局設(shè)備指針則釋放其指向空間
  • 7、編寫(xiě)各個(gè)操作函數(shù)并將函數(shù)名初始化給struct file_operations結(jié)構(gòu)體變量

驗(yàn)證步驟:

  • 1、編寫(xiě)驅(qū)動(dòng)代碼
  • 2、make生成ko文件
  • 3、insmod內(nèi)核模塊
  • 4、查閱字符設(shè)備用到的設(shè)備號(hào)(主設(shè)備號(hào)):cat /proc/devices | grep 申請(qǐng)?jiān)O(shè)備號(hào)時(shí)用的名字
  • 5、創(chuàng)建設(shè)備文件(設(shè)備節(jié)點(diǎn)) : mknod /dev/??? c 上一步查詢(xún)到的主設(shè)備號(hào) 代碼中指定初始次設(shè)備號(hào)
  • 6、編寫(xiě)app驗(yàn)證驅(qū)動(dòng)(testmychar_app.c)
  • 7、編譯運(yùn)行app,dmesg命令查看內(nèi)核打印信息

示例:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>//設(shè)備結(jié)構(gòu)體
struct cdev cdev;//設(shè)備信息
dev_t id;
int major, minor;//驅(qū)動(dòng)操作函數(shù)
//打開(kāi)設(shè)備
int char_open (struct inode * inode, struct file * f)	//打開(kāi)設(shè)備
{return 0;
}//讀
ssize_t char_read (struct file * f, char __user * user, size_t size, loff_t * loff)	//讀設(shè)備
{return size;
}//寫(xiě)
ssize_t char_write (struct file * d , const char __user * user, size_t size, loff_t * loff)    //寫(xiě)設(shè)備
{return size;
}//關(guān)閉
int char_close (struct inode * inod, struct file * f)	//關(guān)閉設(shè)備
{return 0;
}struct file_operations fops = {.owner = THIS_MODULE,.open = char_open,.release = char_close,.write = char_write,.read = char_read,
};int __init init_test(void)
{int ret;//申請(qǐng)?jiān)O(shè)備號(hào)(自動(dòng)分配)alloc_chrdev_region(&id, 0, 1, "char");if(ret){printk("alloc err \r\n");return -EIO;}//初始化設(shè)備結(jié)構(gòu)體cdev_init(&cdev, &fops);//設(shè)置cdev的owner成員為T(mén)HIS_MODULEcdev.owner = THIS_MODULE;//添加字符設(shè)備到內(nèi)核cdev_add(&cdev, id, 1);return 0;
}void __exit exit_test(void)
{//移除設(shè)備cdev_del(&cdev);//注銷(xiāo)設(shè)備號(hào)unregister_chrdev_region(id, 1);
}	MODULE_LICENSE("GPL");
module_init(init_test);
module_exit(exit_test);

五、字符設(shè)備驅(qū)動(dòng)框架解析

設(shè)備的操作函數(shù)如果比喻為樁的話(huà),則:

  • 驅(qū)動(dòng)實(shí)現(xiàn)操作函數(shù):做樁
  • insmod調(diào)用init函數(shù):釘樁
  • 應(yīng)用層通過(guò)系統(tǒng)調(diào)用函數(shù)間接調(diào)用這些設(shè)備的操作函數(shù):用樁
  • rmmod調(diào)用exit函數(shù):拔樁

操作函數(shù)中常用的結(jié)構(gòu)體

  • 1、內(nèi)核中記錄文件信息的結(jié)構(gòu)體
struct inode{//....dev_t  i_rdev;//設(shè)備號(hào)struct cdev  *i_cdev;//如果是字符設(shè)備才有此成員,指向?qū)?yīng)設(shè)備驅(qū)動(dòng)程序中的加入系統(tǒng)的struct cdev對(duì)象//....
}
/*1、該結(jié)構(gòu)體對(duì)象對(duì)應(yīng)著一個(gè)實(shí)際的設(shè)備,一對(duì)一2、open一個(gè)文件時(shí),如果內(nèi)核中存在該文件對(duì)應(yīng)的inode對(duì)象就不再創(chuàng)建,不存在則創(chuàng)建3、內(nèi)核中用此類(lèi)型關(guān)聯(lián)到此文件的操作函數(shù)集(對(duì)設(shè)備而言就是關(guān)聯(lián)到具體的驅(qū)動(dòng)代碼)
*/
  • 2、讀寫(xiě)文件內(nèi)容過(guò)程中用到的一些控制數(shù)據(jù)組合的對(duì)象
struct file
{//...mode_t?f_mode;//不同用戶(hù)的操作權(quán)限,驅(qū)動(dòng)一般不用loff_t?f_pos;//數(shù)據(jù)位置指示器,需要控制數(shù)據(jù)開(kāi)始讀寫(xiě)位置的設(shè)備有用unsigned?int?f_flags;//open是的第二個(gè)參數(shù)flags存放在此,驅(qū)動(dòng)中常用struct?file_operations?*f_op;//open時(shí)從struct inode中i_cdev的對(duì)應(yīng)成員獲得地址。驅(qū)動(dòng)開(kāi)發(fā)中用來(lái)協(xié)助理解工作原理,內(nèi)核中使用void?*private_data;//本次打開(kāi)文件的私有數(shù)據(jù)驅(qū)動(dòng)中常用來(lái)在幾個(gè)操作函數(shù)中傳遞數(shù)據(jù)struct?dentry?*f_dentry;//驅(qū)動(dòng)中一般不用,除非需要訪問(wèn)對(duì)應(yīng)文件的inode,用法flip->f_dentry->d_inodeint refcnt;//引用計(jì)數(shù),保存著該對(duì)象地址的位置個(gè)數(shù),close時(shí)發(fā)現(xiàn)refcnt為0才會(huì)銷(xiāo)毀該struct file對(duì)象//...
};
/*1、open函數(shù)被調(diào)用一次,則創(chuàng)建一個(gè)該對(duì)象,可以認(rèn)為一個(gè)該對(duì)象對(duì)應(yīng)一次指定文件的操作2、open一個(gè)文件多次,每次open都會(huì)創(chuàng)建一個(gè)該對(duì)象3、文件描述符中存放的地址指向該類(lèi)型的對(duì)象4、每個(gè)文件描述符都對(duì)應(yīng)一個(gè)struct file對(duì)象的地址
*/

字符設(shè)備驅(qū)動(dòng)程序框架

  • 驅(qū)動(dòng)實(shí)現(xiàn)端:
    在這里插入圖片描述

  • 驅(qū)動(dòng)使用端:
    在這里插入圖片描述

參考原理圖

在這里插入圖片描述

常用操作函數(shù)

int (*open) (struct inode *, struct file *);	//打開(kāi)設(shè)備
/*指向函數(shù)一般用來(lái)對(duì)設(shè)備進(jìn)行硬件上的初始化,對(duì)于一些簡(jiǎn)單的設(shè)備該函數(shù)只需要return 0,對(duì)應(yīng)open系統(tǒng)調(diào)用,是open系統(tǒng)調(diào)用函數(shù)實(shí)現(xiàn)過(guò)程中調(diào)用的函數(shù),
*/int (*release) (struct inode *, struct file *);	//關(guān)閉設(shè)備
/*,指向函數(shù)一般用來(lái)對(duì)設(shè)備進(jìn)行硬件上的關(guān)閉操作,對(duì)于一些簡(jiǎn)單的設(shè)備該函數(shù)只需要return 0,對(duì)應(yīng)close系統(tǒng)調(diào)用,是close系統(tǒng)調(diào)用函數(shù)實(shí)現(xiàn)過(guò)程中調(diào)用的函數(shù)
*/ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);	//讀設(shè)備
/*指向函數(shù)用來(lái)將設(shè)備產(chǎn)生的數(shù)據(jù)讀到用戶(hù)空間,對(duì)應(yīng)read系統(tǒng)調(diào)用,是read系統(tǒng)調(diào)用函數(shù)實(shí)現(xiàn)過(guò)程中調(diào)用的函數(shù)
*/ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);    //寫(xiě)設(shè)備
/*指向函數(shù)用來(lái)將用戶(hù)空間的數(shù)據(jù)寫(xiě)進(jìn)設(shè)備,對(duì)應(yīng)write系統(tǒng)調(diào)用,是write系統(tǒng)調(diào)用函數(shù)實(shí)現(xiàn)過(guò)程中調(diào)用的函數(shù)
*/loff_t (*llseek) (struct file *, loff_t, int);		//數(shù)據(jù)操作位置的定位
/*指向函數(shù)用來(lái)獲取或設(shè)置設(shè)備數(shù)據(jù)的開(kāi)始操作位置(位置指示器),對(duì)應(yīng)lseek系統(tǒng)調(diào)用,是lseek系統(tǒng)調(diào)用函數(shù)實(shí)現(xiàn)過(guò)程中調(diào)用的函數(shù)
*/long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);//讀寫(xiě)設(shè)備參數(shù),讀設(shè)備狀態(tài)、控制設(shè)備
/*指向函數(shù)用來(lái)獲取、設(shè)置設(shè)備一些屬性或設(shè)備的工作方式等非數(shù)據(jù)讀寫(xiě)操作,對(duì)應(yīng)ioctl系統(tǒng)調(diào)用,是ioctl系統(tǒng)調(diào)用函數(shù)實(shí)現(xiàn)過(guò)程中調(diào)用的函數(shù)
*/unsigned int (*poll) (struct file *, struct poll_table_struct *);//POLL機(jī)制,實(shí)現(xiàn)對(duì)設(shè)備的多路復(fù)用方式的訪問(wèn)
/*指向函數(shù)用來(lái)協(xié)助多路復(fù)用機(jī)制完成對(duì)本設(shè)備可讀、可寫(xiě)數(shù)據(jù)的監(jiān)控,對(duì)應(yīng)select、poll、epoll_wait系統(tǒng)調(diào)用,是select、poll、epoll_wait系統(tǒng)調(diào)用函數(shù)實(shí)現(xiàn)過(guò)程中調(diào)用的函數(shù)
*/int (*fasync) (int, struct file *, int); //信號(hào)驅(qū)動(dòng)
/*指向函數(shù)用來(lái)創(chuàng)建信號(hào)驅(qū)動(dòng)機(jī)制的引擎,對(duì)應(yīng)fcntl系統(tǒng)調(diào)用的FASYNC標(biāo)記設(shè)置,是fcntl系統(tǒng)調(diào)用函數(shù)FASYNC標(biāo)記設(shè)置過(guò)程中調(diào)用的函數(shù)
*/

六、讀操作實(shí)現(xiàn)

ssize_t xxx_read(struct file *filp, char __user *pbuf, size_t count, loff_t *ppos);
完成功能:讀取設(shè)備產(chǎn)生的數(shù)據(jù)
參數(shù):filp:指向open產(chǎn)生的struct file類(lèi)型的對(duì)象,表示本次read對(duì)應(yīng)的那次openpbuf:指向用戶(hù)空間一塊內(nèi)存,用來(lái)保存讀到的數(shù)據(jù)count:用戶(hù)期望讀取的字節(jié)數(shù)ppos:對(duì)于需要位置指示器控制的設(shè)備操作有用,用來(lái)指示讀取的起始位置,讀完后也需要變更位置指示器的指示位置返回值:本次成功讀取的字節(jié)數(shù),失敗返回-1
  • 由于內(nèi)核不能直接和用戶(hù)空間進(jìn)行數(shù)據(jù)傳輸,因此要使用函數(shù)實(shí)現(xiàn):
  • 從內(nèi)核中復(fù)制數(shù)據(jù)到用戶(hù)空間
    #include <asm-generic/uaccess.h>
unsigned long copy_to_user (void __user * to, const void * from, unsigned long n)
成功為返回0,失敗非0

七、寫(xiě)操作實(shí)現(xiàn)

ssize_t xxx_write (struct file *filp, const char __user *pbuf, size_t count, loff_t *ppos);  
完成功能:向設(shè)備寫(xiě)入數(shù)據(jù)
參數(shù):filp:指向open產(chǎn)生的struct file類(lèi)型的對(duì)象,表示本次write對(duì)應(yīng)的那次openpbuf:指向用戶(hù)空間一塊內(nèi)存,用來(lái)保存被寫(xiě)的數(shù)據(jù)count:用戶(hù)期望寫(xiě)入的字節(jié)數(shù)ppos:對(duì)于需要位置指示器控制的設(shè)備操作有用,用來(lái)指示寫(xiě)入的起始位置,寫(xiě)完后也需要變更位置指示器的指示位置返回值:本次成功寫(xiě)入的字節(jié)數(shù),失敗返回-1
  • 從用戶(hù)空間復(fù)制數(shù)據(jù)到內(nèi)核中
    #include <asm-generic/uaccess.h>
unsigned long copy_from_user (void * to, const void __user * from, unsigned long n)成功為返回0,失敗非0

八、ioctl的實(shí)現(xiàn)

  • 可以已知結(jié)構(gòu)體成員獲得所在結(jié)構(gòu)體變量的地址
container_of(成員地址,結(jié)構(gòu)體類(lèi)名,成員的名稱(chēng))
  • ioctl

long xxx_ioctl (struct file *filp, unsigned int cmd, unsigned long arg);
功能:對(duì)相應(yīng)設(shè)備做指定的控制操作(各種屬性的設(shè)置獲取等等)
參數(shù):filp:指向open產(chǎn)生的struct file類(lèi)型的對(duì)象,表示本次ioctl對(duì)應(yīng)的那次opencmd:用來(lái)表示做的是哪一個(gè)操作arg:和cmd配合用的參數(shù)
返回值:成功為0,失敗-1
  • cmd的組成
    在這里插入圖片描述
1. dir(direction),ioctl 命令訪問(wèn)模式(屬性數(shù)據(jù)傳輸方向),占據(jù) 2 bit,可以為 _IOC_NONE、_IOC_READ、_IOC_WRITE、_IOC_READ | _IOC_WRITE,分別指示了四種訪問(wèn)模式:無(wú)數(shù)據(jù)、讀數(shù)據(jù)、寫(xiě)數(shù)據(jù)、讀寫(xiě)數(shù)據(jù);
2. type(device type),設(shè)備類(lèi)型,占據(jù) 8 bit,在一些文獻(xiàn)中翻譯為 “幻數(shù)” 或者 “魔數(shù)”,可以為任意 char 型字符,例如 ‘a(chǎn)’、’b’、’c’ 等等,其主要作用是使 ioctl 命令有唯一的設(shè)備標(biāo)識(shí);
3. nr(number),命令編號(hào)/序數(shù),占據(jù) 8 bit,可以為任意 unsigned char 型數(shù)據(jù),取值范圍 0~255,如果定義了多個(gè) ioctl 命令,通常從 0 開(kāi)始編號(hào)遞增;
4. size,涉及到 ioctl 函數(shù) 第三個(gè)參數(shù) arg ,占據(jù) 13bit 或者 14bit(體系相關(guān),arm 架構(gòu)一般為 14 位),指定了 arg 的數(shù)據(jù)類(lèi)型及長(zhǎng)度,如果在驅(qū)動(dòng)的 ioctl 實(shí)現(xiàn)中不檢查,通??梢院雎栽搮?shù);

九、創(chuàng)建多個(gè)次設(shè)備

每一個(gè)具體設(shè)備(次設(shè)備不一樣),必須有一個(gè)struct cdev來(lái)代表它
并且需要以下三個(gè)操作:

  • cdev_init
  • cdev.owner賦值
  • cdev_add

十、(多個(gè)次設(shè)備同時(shí)獲取設(shè)備號(hào)、同時(shí)創(chuàng)建設(shè)備)在驅(qū)動(dòng)中創(chuàng)建設(shè)備

內(nèi)核中 實(shí)現(xiàn) 創(chuàng)建 設(shè)備文件 /dev/xxx

1、創(chuàng)建設(shè)備

  • 手動(dòng)方式 創(chuàng)建設(shè)備文件
	sudo mknod /dev/xxx  c      243      0 設(shè)備節(jié)點(diǎn)名  字符型  主設(shè)備號(hào) 次設(shè)備號(hào) 在Linux內(nèi)核 3.0后 引入了 udev服務(wù)  該服務(wù)可以用于 檢查驅(qū)動(dòng)的 設(shè)備文件添加請(qǐng)求, 然后添加對(duì)應(yīng)的設(shè)備文件 
  • 自動(dòng)創(chuàng)建設(shè)備文件

#include <linux/device.h>

struct class * class_create(owner, name);
owner 所有者  THIS_MODULE 
name  類(lèi)的名字 創(chuàng)建之后可以看到該名字 `cat /proc/devices | grep 類(lèi)的名字`返回值:  struct class *  出差 返回 錯(cuò)誤指針

2、關(guān)聯(lián)設(shè)備節(jié)點(diǎn)與設(shè)備文件名

#include <linux/device.h>

struct device *device_create(struct class *cls, struct device *parent,dev_t devt, void *drvdata,const char *fmt, ...);
例子:dev = device_create(cls, NULL, id, NULL, "char%d", 1);

3、卸載驅(qū)動(dòng)時(shí)銷(xiāo)毀設(shè)備節(jié)點(diǎn)

void device_destroy(struct class *cls, dev_t devt);

4、銷(xiāo)毀類(lèi)

void class_destroy(struct class *cls);

示例:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>//設(shè)備結(jié)構(gòu)體
struct cdev cdev;//設(shè)備信息
dev_t id;
int major, minor;//class類(lèi)型
struct class *cls;struct device *dev;//驅(qū)動(dòng)操作函數(shù)
//打開(kāi)設(shè)備
int char_open (struct inode * inode, struct file * f)	//打開(kāi)設(shè)備
{return 0;
}//讀
ssize_t char_read (struct file * f, char __user * user, size_t size, loff_t * loff)	//讀設(shè)備
{return size;
}//寫(xiě)
ssize_t char_write (struct file * d , const char __user * user, size_t size, loff_t * loff)    //寫(xiě)設(shè)備
{return size;
}//關(guān)閉
int char_close (struct inode * inod, struct file * f)	//關(guān)閉設(shè)備
{return 0;
}struct file_operations fops = {.owner = THIS_MODULE,.open = char_open,.release = char_close,.write = char_write,.read = char_read,
};int __init init_test(void)
{int ret;int i;//申請(qǐng)?jiān)O(shè)備號(hào)(自動(dòng)分配)四個(gè)設(shè)備alloc_chrdev_region(&id, 0, 4, "char_dev");if(ret){printk("alloc err \r\n");return -EIO;}//初始化設(shè)備結(jié)構(gòu)體cdev_init(&cdev, &fops);//設(shè)置cdev的owner成員為T(mén)HIS_MODULEcdev.owner = THIS_MODULE;//添加字符設(shè)備到內(nèi)核ret = cdev_add(&cdev, id, 4);if(ret){printk("cdev add err \r\n");goto add_err;}//生成設(shè)備文件cls = class_create(THIS_MODULE, "char_class");if(IS_ERR(cls)){printk("class create err\r\n");goto class_err;		}//關(guān)聯(lián)設(shè)備節(jié)點(diǎn)和設(shè)備名  循環(huán)創(chuàng)建4個(gè)for(i =0 ;i < 4; i++){dev = device_create(cls, NULL, id + i, NULL, "char_dev%d", i);if(IS_ERR(dev)){printk("device create err\r\n");goto device_err;	}	}return 0;//回滾
device_err:for(i--; i >= 0; i--){device_destroy(cls, id + i);}//銷(xiāo)毀classclass_destroy(cls);class_err://移除設(shè)備cdev_del(&cdev);add_err://注銷(xiāo)設(shè)備號(hào)unregister_chrdev_region(id, 4);return -EIO;
}void __exit exit_test(void)
{int i;//取消設(shè)備節(jié)點(diǎn)for(i =0 ;i < 4; i++){device_destroy(cls, id + i);}//銷(xiāo)毀classclass_destroy(cls);//移除設(shè)備cdev_del(&cdev);//注銷(xiāo)設(shè)備號(hào)unregister_chrdev_region(id, 4);
}	MODULE_LICENSE("GPL");
module_init(init_test);
module_exit(exit_test);
http://www.risenshineclean.com/news/5193.html

相關(guān)文章:

  • php做網(wǎng)站怎么樣網(wǎng)站收錄查詢(xún)系統(tǒng)
  • 伙購(gòu)網(wǎng)官方網(wǎng)站seo刷排名公司
  • 關(guān)于網(wǎng)站開(kāi)發(fā)的學(xué)校武漢全網(wǎng)推廣
  • 網(wǎng)絡(luò)平臺(tái)怎么弄湖南seo推廣
  • wordpress qtan專(zhuān)業(yè)搜索引擎優(yōu)化電話(huà)
  • 投票網(wǎng)站制作廣州市疫情最新
  • 哪些網(wǎng)站做外鏈好瀏陽(yáng)廖主任打人案
  • 網(wǎng)站設(shè)計(jì)導(dǎo)航欄高度中國(guó)萬(wàn)網(wǎng)域名注冊(cè)
  • 網(wǎng)站建設(shè)_超速云建站重慶seo標(biāo)準(zhǔn)
  • 微號(hào)網(wǎng)站開(kāi)發(fā)長(zhǎng)沙網(wǎng)站seo哪家公司好
  • 網(wǎng)站上的搜索功能是怎么做的seo技術(shù)快速網(wǎng)站排名
  • 云南網(wǎng)站建設(shè)優(yōu)選平臺(tái)專(zhuān)業(yè)seo整站優(yōu)化
  • 速賣(mài)通開(kāi)店流程及費(fèi)用星巴克seo網(wǎng)絡(luò)推廣
  • 視頻網(wǎng)站會(huì)員系統(tǒng)怎么做seo交互論壇
  • 網(wǎng)站防護(hù)找誰(shuí)做seo實(shí)戰(zhàn)密碼在線(xiàn)閱讀
  • 商城網(wǎng)站建設(shè)哪家好站長(zhǎng)平臺(tái)官網(wǎng)
  • 網(wǎng)站如何做rss訂閱長(zhǎng)沙做網(wǎng)站的公司有哪些
  • 怎么做網(wǎng)頁(yè)鏈接教程網(wǎng)站首頁(yè)關(guān)鍵詞如何優(yōu)化
  • 網(wǎng)架加工安裝一體的公司外鏈seo
  • 校園網(wǎng)站建設(shè)背景國(guó)內(nèi)做網(wǎng)站比較好的公司
  • wordpress點(diǎn)贊 1岳陽(yáng)seo快速排名
  • 石家莊商城網(wǎng)站搭建多少錢(qián)西安百度推廣運(yùn)營(yíng)
  • 百度做的網(wǎng)站seo實(shí)戰(zhàn)
  • 綜合商城網(wǎng)站程序營(yíng)銷(xiāo)策劃書(shū)范文案例
  • 襄陽(yáng)營(yíng)銷(xiāo)型網(wǎng)站寶雞seo培訓(xùn)
  • 江西網(wǎng)站制作企業(yè)qq一年多少費(fèi)用
  • 哪個(gè)網(wǎng)站可以做旅行攻略seo推廣排名公司
  • 網(wǎng)站建設(shè)思路品牌推廣專(zhuān)員
  • 蕪湖哪家公司做網(wǎng)站不錯(cuò)什么叫seo網(wǎng)絡(luò)推廣
  • 互聯(lián)網(wǎng)app網(wǎng)站建設(shè)方案模板百度seo關(guān)鍵詞優(yōu)化公司