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

當前位置: 首頁 > news >正文

網(wǎng)站開發(fā)使用哪種語言免費網(wǎng)站站長查詢

網(wǎng)站開發(fā)使用哪種語言,免費網(wǎng)站站長查詢,濟寧建設企業(yè)網(wǎng)站,做編程網(wǎng)站有哪些方面文章目錄 注冊雜項設備驅(qū)動模塊傳參注冊字符設備 開發(fā)環(huán)境: windows ubuntu18.04 迅為rk3568開發(fā)板 注冊雜項設備 相較于字符設備,雜項設備有以下兩個優(yōu)點: 節(jié)省主設備號:雜項設備的主設備號固定為 10,在系統(tǒng)中注冊多個 misc 設備驅(qū)動時&…

文章目錄

  • 注冊雜項設備
  • 驅(qū)動模塊傳參
  • 注冊字符設備

開發(fā)環(huán)境: windows + ubuntu18.04 + 迅為rk3568開發(fā)板

注冊雜項設備

相較于字符設備,雜項設備有以下兩個優(yōu)點:

  • 節(jié)省主設備號:雜項設備的主設備號固定為 10,在系統(tǒng)中注冊多個 misc 設備驅(qū)動時,只需使用子設備號進行區(qū)分即可。
  • 使用簡單:相比如普通的字符設備驅(qū)動, misc驅(qū)動只需要將基本信息通過結構體傳遞給相應處理函數(shù)即可。

在linxu系統(tǒng)中可使用 cat /proc/misc 命令查看系統(tǒng)中的雜項設備。注冊雜項設備的步驟:

  • 1.填充設備操作集結構體struct file_operations

  • 2.填充雜項設備結構體struct miscdevice;

  • 3.使用函數(shù)misc_register注冊雜項設備;

  • 4.使用函數(shù)misc_deregister卸載雜項設備;

上面三步可使用下面函數(shù)直觀用表達,即:

static struct file_operations xxx_fops{.owner = THIS_MODULE, .read = xxx_read, ....
};
struct miscdevice xxx_dev{.minor = MISC_DYNAMIC_MINOR, .name = "xxx", .fops = &xxx_fops
};
static int __init xxx_init(void) //驅(qū)動入口函數(shù)
{int ret;printk(KERN_EMERG "xxx_init\r\n");ret = misc_register(&xxx_dev);//注冊雜項設備if(ret<0){printk( "misc_register failed\r\n");return -1;}printk( "misc_register ok\r\n");return 0;
}
static void __exit xxx_exit(void) //驅(qū)動出口函數(shù)
{printk(KERN_EMERG "xxx_exit\r\n");misc_deregister(&xxx_dev); //卸載雜項設備
}
module_init(xxx_init); //注冊入口函數(shù)
module_exit(xxx_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xxx");

具體實現(xiàn)注冊一個雜項設備的示例代碼如下:

#include <linux/kernel.h>
#include <linux/init.h>              //初始化頭文件
#include <linux/module.h>            //最基本的文件,支持動態(tài)添加和卸載模塊。
#include <linux/miscdevice.h>        //注冊雜項設備頭文件
#include <linux/fs.h>                //注冊設備節(jié)點的文件結構體
#include <linux/uaccess.h>// 打開雜項設備
int _open(struct inode *inode,struct file*file)
{printk(KERN_EMERG"hello misc");return 0;
}// 關閉雜項設備
int close(struct inode * inode, struct file *file)
{printk(KERN_EMERG"close");return 0;
}// 讀取雜項設備中的數(shù)據(jù)
ssize_t misc_read (struct file *file, char __user *buff, size_t size, loff_t *loff)
{char kbuff[32] = "kernel";if(copy_to_user(buff,kbuff,strlen(kbuff)) != 0) // 將內(nèi)核中的數(shù)據(jù)給應用{printk("copy_to_user error\r\n");return -1;}	printk(KERN_EMERG"copy_to_user is successful\r\n");return size;
}// 寫入數(shù)據(jù)到雜項設備中
ssize_t misc_write (struct file *file, const char __user *buff, size_t size, loff_t *loff)
{char kbuff[32] ;if(copy_from_user(kbuff,buff,size)!= 0) // 從應用那兒獲取數(shù)據(jù){printk("copy_from_user error\r\n");return -1;}	printk(KERN_EMERG"copy_from_user data:%s\r\n",kbuff);return size;
}// 設備文件描述集  
struct file_operations misc_fops ={.owner = THIS_MODULE,.open = misc_open,.release = close,.read = misc_read,.write = misc_write
};struct miscdevice misc_dev = {.minor = MISC_DYNAMIC_MINOR,.name = "hello_misc", // 雜項設備名   注冊成功后會在 /dev目錄下顯示.fops = &misc_fops
};// 驅(qū)動的入口函數(shù)
static int __init misc_init(void)
{int ret = 0;ret = misc_register(&misc_dev);if(ret < 0)printk(KERN_EMERG"misc register is error\r\n.");elseprintk(KERN_EMERG"misc register is seccussful\r\n.");return 0;
}//驅(qū)動的出口函數(shù)
static void __exit misc_exit(void)
{misc_deregister(&misc_dev);printk(KERN_EMERG"baibai\r\n");
}module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("zhouxianjie0716@qq.com");

編譯傳送到開發(fā)板上后,先試用insmod +驅(qū)動名.ko掛載驅(qū)動,其結果為:
在這里插入圖片描述

上述驅(qū)動代碼的測試代碼如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc,char *argv[])
{char filePath[] = "/dev/hello_misc";// 打開文件int fd = open(filePath,O_RDWR);if(fd < 0){printf("opening is failed.\n");return -1;}elseprintf("opening is successful.\n");// 讀取char buff1[32],buff2[32] = "hello this is app";read(fd,buff1,sizeof(buff1));printf("buff1 is %s.\n",buff1);// 寫入write(fd,buff2,sizeof(buff2));	close(fd);return 0;
}

使用./+程序名運行測試代碼后,得結果如下:
在這里插入圖片描述


驅(qū)動模塊傳參

總所周知,應用程序傳參是通過shell終端傳,只要將main函數(shù)按照下面格式書寫即可完成傳參操作

int main(int argc ,char *argv[])
{return 0;
}

相比之下,驅(qū)動模塊傳遞參數(shù)需要借助其他函數(shù)完成傳參操作:

1. 傳遞單個參數(shù)給內(nèi)核

module_param(name, type, perm)

參數(shù)解釋:

  • name:參數(shù)名,既是外部參數(shù)名,又是內(nèi)部參數(shù)名。

  • type:參數(shù)的數(shù)據(jù)類型,可取int、charp等。

  • perm:訪問權限。八進制,如:0777。0表示該參數(shù)在文件系統(tǒng)中不可見。

注意:傳遞字符作為參數(shù)時數(shù)據(jù)類為charp,而不是char.

2.傳遞數(shù)組給內(nèi)核

module_param_array(name, type, nump, perm)
  • module_param_array(name,type,nump,perm)
  • name:數(shù)組參數(shù)名,既是外部參數(shù),又是內(nèi)部參數(shù)
  • type:參數(shù)的數(shù)據(jù)類型
  • nump:終端傳給數(shù)組的實際元素個數(shù)(指針變量)
  • perm:訪問權限,0644。0表示該參數(shù)在文件系統(tǒng)中不可見

3.傳遞字符串給內(nèi)核

module_param_string(name, string, len, perm)
  • name:參數(shù)名,外部參數(shù)名
  • string:內(nèi)部參數(shù)名(內(nèi)部字符數(shù)組名)
  • len:數(shù)組長度
  • perm:訪問權限,0644。0表示該參數(shù)在文件系統(tǒng)中不可見

傳遞參給內(nèi)核的作用:

  • 1.設置驅(qū)動的相關參數(shù),如:設備數(shù)量、設備緩沖區(qū)大小等等。
  • 2.可進行安全校驗,放置驅(qū)動被他人盜用。

說明
參數(shù)傳遞的適用時機為 加載驅(qū)動到內(nèi)核時,命令形式為:insmod +驅(qū)動名.ko +參數(shù)1名=參數(shù)值 參數(shù)2名=參數(shù)值 ……。例如下面示例中使用insmod file.ko date=12傳遞參數(shù):

#include <linux/module.h>
#include <linux/init.h>// 保存參數(shù)
static int date;
static int date1;
static int data[5];
static int count;
static char str[32];
static char *strData;// 傳遞單個參數(shù)
module_param(date,int,S_IRUGO|S_IWUSR); // 可讀可寫
module_param(date1,int,S_IRUGO); // 可讀可寫
module_param(strData,charp,S_IRUGO); // 可讀// 傳遞多個參數(shù)
module_param_array(data,int,&count,S_IRUGO); // 可讀
module_param_string(str,str,sizeof(str),S_IRUGO); // 可讀// 驅(qū)動的入口函數(shù)
static int __init dev_init(void)
{int i=0;if(strcmp(str,"myTest")!=0){printk("dev_init error\r\n");return -1;}printk("---------------------------------------\r\n");printk(KERN_EMERG"dev_init is successful!\r\n");for(i=0;i<count;++i)printk("data[%d] = %d \r\n",i,data[i]);printk("str:%s  strData:%s\r\n",str,strData);printk("date:%d  count:%d\r\n",date,count);data[1] = 111;date = 10;date1 = 111;return 0;
}//驅(qū)動的出口函數(shù)
static void __exit dev_exit(void)
{int i=0;for( i=0;i<count;++i)printk("data[%d] = %d \r\n",i,data[i]);printk("date:%d  count:%d\r\n",date,count);printk(KERN_EMERG"dev_exit is successful\r\n");
}module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("zhouxianjie0716@qq.com");

注冊字符設備

步驟一:驅(qū)動初始化,需要申請設備號,初始化并且注冊cdev結構體,初始化硬件;

可使用動態(tài)申請或靜態(tài)申請設備號,其中動態(tài)申請設備號一般在235-255,靜態(tài)申請則一般由用戶手動輸入。

靜態(tài)申請的函數(shù)原型為:

 int register_chrdev_region(dev_t, unsigned, const char *);

參數(shù)含義:

  • from: 自定義的 dev_t 類型設備號。
  • count: 申請設備的數(shù)量。
  • name: 申請的設備名稱。
    函數(shù)返回值:申請成功返回 0,申請失敗返回負數(shù)。

動態(tài)申請的函數(shù)原型為:

 int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);

參數(shù)含義:

  • dev : 會將申請完成的設備號保存在 dev 變量中。
  • baseminor: 次設備號可申請的最小值。
  • count: 申請設備的數(shù)量。
  • name: 申請的設備名稱。
    函數(shù)返回值:申請成功返回 0,申請失敗返回負

Linux 內(nèi)核中將字符設備抽象成一個具體的數(shù)據(jù)結構 (struct cdev), 我們可以理解為字符設備對象,cdev 記錄了字符設備號、內(nèi)核對象、文件操作 file_operations 結構體(設備的打開、讀寫、關閉等操作接口)等信息:

struct cdev {struct kobject kobj; //內(nèi)嵌的內(nèi)核對象.struct module *owner; //該字符設備所在的內(nèi)核模塊的對象指針. const struct file_operations *ops; //該結構描述了字符設備所能實現(xiàn)的方法,是極為關鍵的一個結構體.struct list_head list; //用來將已經(jīng)向內(nèi)核注冊的所有字符設備形成鏈表. dev_t dev; //字符設備的設備號,由主設備號和次設備號構成. unsigned int count; //隸屬于同一主設備號的次設備號的個數(shù). 
};

初始化設備描述集cdev結構體的函數(shù)原型為:

void cdev_init(struct cdev *, const struct file_operations *);

參數(shù)含義:

  • 參數(shù)1:表示是抽象設備結構體;
  • 參數(shù)2:表示文件操作集;

注冊設備到內(nèi)驅(qū)使用下面函數(shù)

int cdev_add(struct cdev *, dev_t,  unsigned);

參數(shù)含義:

  • 參數(shù)1:為要添加的 struct cdev 類型的結構體
  • 參數(shù)2:為申請的字符設備號
  • 參數(shù)3:為和該設備關聯(lián)的設備編號的數(shù)量
    若函數(shù)在內(nèi)核中添加成功返回 0,添加失敗返回負數(shù)。

步驟二:構建設備文件操作描述集file_operations

也就是read、write、open、close等函數(shù)。

步驟三:生成并且添加設備節(jié)點

  • 手動添加設備節(jié)點:也就是在加載驅(qū)動到內(nèi)核時添加,即mknod + 路徑/設備名 +設備類型 + 主設備號 + 次設備號
  • 自動添加設備節(jié)點:初始化內(nèi)核時,使用函數(shù)自動添加。即先試用函數(shù)class_create創(chuàng)建一個類,在使用函數(shù)device_create創(chuàng)建并且添加設備節(jié)點。

class_create函數(shù)說明:

#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \ __class_create(owner, name, &__key); \
})

函數(shù)作用:
用于動態(tài)創(chuàng)建設備的邏輯類,并完成部分字段的初始化,然后將其添加進 Linux 內(nèi)核系統(tǒng)。

參數(shù)含義:

  • owner:指向函數(shù)即將創(chuàng)建的這個 struct class 的模塊。一般為 THIS_MODULE。
  • name:代表即將創(chuàng)建的 struct class 變量的名字。
    返回值:struct class * 類型的類。

device_create函數(shù)說明:


struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt,...);

函數(shù)作用:
用來在 class 類中下創(chuàng)建一個設備屬性文件,udev 會自動識別從而進行設備節(jié)點的創(chuàng)建。

參數(shù)含義:

  • cls:指定所要創(chuàng)建的設備所從屬的類。
  • parent:指定該設備的父設備,如果沒有就指定為 NULL。
  • devt:指定創(chuàng)建設備的設備號。
  • drvdata:被添加到該設備回調(diào)的數(shù)據(jù),沒有則指定為 NULL。
  • fmt:添加到系統(tǒng)的設備節(jié)點名稱。

返回值:struct device * 類型結構體的設備

步驟四:注銷字符設備驅(qū)動

  • 步驟一:使用函數(shù)unregister_chrdev_region釋放設備號
void unregister_chrdev_region(dev_t, unsigned)

該函數(shù)只有一個參數(shù),為要刪除設備的設備號,并且函數(shù)無返回值。

  • 步驟二:使用函數(shù)cdev_del步驟二:刪除設備操作集卸載cdev
void cdev_del(struct cdev *);

該函數(shù)只有一個參數(shù),為要刪除的 struct cdev 類型的結構體,并且函數(shù)無返回值。

  • 步驟三:使用函數(shù)device_destroy卸載設備
void device_destroy(struct class *cls, dev_t devt);

用來刪除 cls 類中的devt設備屬性文件,udev 會自動識別從而進行設備節(jié)點的刪除。

  • 步驟四:使用函數(shù)class_destroy刪除類class
 void class_destroy(struct class *cls);

該函數(shù)只有一個參數(shù),為要刪除的類,并且函數(shù)無返回值。

示例代碼

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>#define DEVICE_NUMBER 1 // 設備數(shù)量
#define DEVICE_SNAME "schrdev" // 靜態(tài)申請時設備名
#define DEVICE_ANAME "achrdev" // 動態(tài)申請時設備名
#define DEVICE_MINOR_NUM 0 // 次設備號起始地址
#define DEVICE_CLASS_NAME "myTestClass" // 類名
#define DEVICE_MYNAME "mytest"// 打開設備
int chrdev_open(struct inode*inode,struct file*file)
{printk("chrdev_open is opened\r\n");return 0;
}// 保存設備號 其中前12位為主設備號 后20位為次設備號
static dev_t dev_num;// 定義主設備號 次設備號
static int major_num,minor_num; // 設備信息描述集
struct cdev cdev;// 類描述集
struct class *cls;// 設備描述集
struct device*device;// 傳遞單個參數(shù)
module_param(major_num,int,S_IRUGO); // 可讀
module_param(minor_num,int,S_IRUGO); // 可讀// 文件操作集
struct file_operations chrdev_opr = {.owner = THIS_MODULE,.open = chrdev_open
};// 驅(qū)動的入口函數(shù)
static int __init dev_init(void)
{int ret;/* 步驟一:申請設備號 */// 有傳遞主設備號就靜態(tài)申請if(major_num){	dev_num = MKDEV(major_num, minor_num);//將主設備號 次設備號合并成設備號//參數(shù)分別表示 設備號 設備數(shù)量 設備名稱ret = register_chrdev_region(dev_num, DEVICE_NUMBER, DEVICE_SNAME); if(ret < 0){printk("dev_init error\r\n");return -1;}}	// 否則就動態(tài)申請else{// 參數(shù):設備號 次設備號起始地址 設備數(shù)量 設備名稱ret = alloc_chrdev_region(&dev_num , DEVICE_MINOR_NUM, DEVICE_NUMBER, DEVICE_ANAME);if(ret < 0){printk("dev_init error\r\n");return -1;}// 獲取主設備號 次設備號major_num = MAJOR(dev_num);minor_num = MINOR(dev_num);}printk("---------------------------------------\r\n");printk("dev_num:%d major_num:%d minor_num:%d\r\n",dev_num,major_num,minor_num);/* 步驟二:初始化設備 */// 初始化cdevcdev.owner = THIS_MODULE;// 初始化設備  cdev_init(&cdev, &chrdev_opr);/* 步驟三:注冊設備到內(nèi)核 *///添加(注冊)到內(nèi)核 參數(shù): 設備   設備號  設備數(shù)量cdev_add(&cdev, dev_num, DEVICE_NUMBER);/* 步驟四:先創(chuàng)建類再自動創(chuàng)建添加設備名稱*/// 創(chuàng)建類 參數(shù)1: 類的歸屬   參數(shù)2: 類名cls = class_create(THIS_MODULE,DEVICE_CLASS_NAME);// 創(chuàng)建設備 參數(shù)1: 歸屬到類   參數(shù)2:設備的父設備 參數(shù)3:設備號 參數(shù)4:添加到設備的回調(diào)數(shù)據(jù) 參數(shù)5:設備名device = device_create(cls,NULL,dev_num,NULL,DEVICE_MYNAME);printk("auto add device name\r\n");return 0;
}//驅(qū)動的出口函數(shù)
static void __exit dev_exit(void)
{/* 步驟一:注銷設備號 參數(shù):設備號   設備數(shù)量 */ unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);/* 步驟二:刪除設備操作集 */cdev_del(&cdev);/* 步驟三:刪除設備*/device_destroy(cls,dev_num);/* 步驟四: 刪除類*/class_destroy( cls);printk(KERN_EMERG"dev_exit is successful\r\n");
}module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("zhouxianjie0716@qq.com");

使用加載驅(qū)動到內(nèi)核insmod file.ko命令,得結果
在這里插入圖片描述

在測試驅(qū)動前需要使用mknod /dev/mytest c 236 0創(chuàng)建設備文件,命令格式為:mknod + /路徑/設備名稱 +設備類型+主設備號 + 次設備號。

然后就可寫一個應用程序來測試我們的字符驅(qū)動是否成功注冊,測試源碼如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc,char* argv[])
{char name[] = "/dev/mytest";int fd = open(name,O_RDONLY); // 僅讀if(fd < 0){printf("open is failed\n");return -1;}close(fd);return 0;
}

執(zhí)行測試程序后結果如下:
在這里插入圖片描述

注意:在運行測試程序時,一定要先創(chuàng)建驅(qū)動文件,否則就會報段錯誤,具體如下:
在這里插入圖片描述


雜項設備與字符設備的比較

  • 雜項設備的主設備號固定為10,而字符設備的主設備號需要創(chuàng)建。
  • 雜項設備的創(chuàng)建相對簡單,只需要填充設備操作集結構體、雜項設備結構體再注冊即可。而字符設備需要經(jīng)過 申請設備號、初始化并且注冊cdev結構體、初始化硬件、構建設備文件操作描述集、生成并且添加設備節(jié)點。
  • 雜項設備與字符設備都需要構建文件操作描述集。(應用層調(diào)用驅(qū)動的核心)
http://m.risenshineclean.com/news/32826.html

相關文章:

  • 個人做網(wǎng)站如何賺錢嗎百度客服電話人工服務熱線電話
  • 北京市網(wǎng)站建設百度搜索推廣怎么做
  • 青島開發(fā)區(qū)網(wǎng)站建設公司汽車seo是什么意思
  • 網(wǎng)站建設與網(wǎng)頁設計如何優(yōu)化百度seo排名
  • 魚滑怎么制作教程搜索引擎優(yōu)化seo的英文全稱是
  • 施工效果圖怎么做關鍵詞搜索優(yōu)化
  • 江蘇做網(wǎng)站公司東莞整站優(yōu)化推廣公司找火速
  • 個人電腦做網(wǎng)站服務器教程制作一個app軟件需要多少錢
  • 利辛做網(wǎng)站搜索引擎關鍵詞怎么選
  • php怎么建立站點下載百度語音導航地圖安裝
  • 如何更新網(wǎng)站緩存濟南網(wǎng)絡優(yōu)化廠家
  • 網(wǎng)站中鏈接怎么做推廣網(wǎng)站公司
  • 網(wǎng)站開發(fā)進度管理表谷歌seo工具
  • 太原網(wǎng)站建設費用上首頁seo
  • 網(wǎng)站一般寬度windows優(yōu)化大師有哪些功能
  • 國內(nèi) 設計網(wǎng)站的公司網(wǎng)站3000行業(yè)關鍵詞
  • 手機網(wǎng)站開發(fā)教程東莞做網(wǎng)站哪家公司好
  • 網(wǎng)站有沒有做網(wǎng)站地圖怎么看今天國際新聞大事
  • 想做一個自己設計公司的網(wǎng)站怎么做的網(wǎng)站推廣公司電話
  • 電腦做系統(tǒng)網(wǎng)站鄭州網(wǎng)站優(yōu)化培訓
  • 軟件工程師是程序員嗎電腦優(yōu)化工具
  • 建設一個大型網(wǎng)站大概費用磁力王
  • 主流門戶網(wǎng)站百度關鍵詞搜索推廣
  • 怎樣設計網(wǎng)頁教程關鍵詞優(yōu)化外包
  • 鄭州電力高等??茖W校哪個專業(yè)好重慶seo和網(wǎng)絡推廣
  • 可視化網(wǎng)站制作軟件站長之家ppt素材
  • 深圳html5網(wǎng)站建設搜索引擎營銷sem
  • 遼寧網(wǎng)站推廣的目的網(wǎng)絡運營是做什么的工作
  • 做外國網(wǎng)站買域名推廣賺錢一個2元
  • 網(wǎng)站建設后期維護小魔仙網(wǎng)絡廣告宣傳平臺