一、什么是雜項設備?
雜項設備(misc device)也是在嵌入式系統中用得比較多的一種設備驅動,
在Linux內核的include\linux目錄下有Miscdevice.h檔案,misc設備定義及其內核提供的相關函式在這里,
其實是因為這些字符設備不符合預先確定的字符設備范疇,所有這些設備采用主設備10,一起歸于misc device,其實misc_register就是用主標號10呼叫register_chrdev()的,
也就是說,misc設備其實也就是特殊的字符設備,
在Linux驅動中把無法歸類的五花八門的設備定義為混雜設備(用miscdevice結構體表述),
miscdevice共享一個主設備號MISC_MAJOR(即10),但次設備號不同,
所有的miscdevice設備形成了一個鏈表,對設備訪問時內核根據次設備號查找對應的miscdevice設備,然后呼叫其file_operations結構中注冊的檔案操作介面進行操作,
在內核中用struct miscdevice表示miscdevice設備,然后呼叫其file_operations結構中注冊的檔案操作介面進行操作,
miscdevice的API實作在drivers/char/misc.c中,
?
二、描述雜項設備的結構
內核用struct miscdevice的結構體來描述雜項設備:
struct miscdevice {
int minor; //次設備號,雜項設備的主設備?10
const char *name; //設備的名稱
const struct file_operations *fops; //檔案操作
/* 下面的成員是供內核使用 ,驅動撰寫不需要理會 */
struct list_head list; //misc_list的鏈表頭
struct device *parent; //父設備
struct device *this_device; //當前設備,是device_create的回傳值
};
minor:次設備號,0~255,當傳遞255時候,會自動由內核分配一個可用次設備號,
name:備名/dev/下的設備節點名,
fops:檔案操作方法指標,
特點:當安裝此類驅動后,會在系統的/dev下生成相應的設備節點檔案,
三、內核提供來撰寫雜項設備的API函式
3.1 注冊函式
| 函式原型 | int misc_register(struct miscdevice * misc) |
| 頭檔案 | #include <linux/miscdevice.h> |
| 功能 | 注冊一個雜項設備 |
| 引數 | misc- 雜項設備的核心結構指標, 至少已經實作minor,name,fops三個成員, |
| 回傳值 | 0,表示注冊成功;負數,注冊失敗, |
3.2 注銷函式
| 函式原型 | int misc_deregister(struct miscdevice *misc) |
| 頭檔案 | #include <linux/miscdevice.h> |
| 功能 | 注銷一個已經存在雜項設備 |
| 引數 | misc,雜項設備的核心結構指標,已經注冊的struct miscdevice結構, |
| 回傳值 | 0,表示注冊成功;負數,注冊失敗, |
四、雜項設備的設備號&特征
設備號是用來標志設備,分為設備號和此設備號,其中雜項設備的設備號如下:
主設備號:固定為10,
次設備號:0~255,
a.主設備號固定為10
b.注冊后會自動在/dev/目錄下生成設備檔案
c.使用一個核心結構 struct miscdevice 封裝起來了,
五、撰寫驅動程式
步驟如下:
1)先寫一個模塊基本代碼
2)增加設備模型所需要的頭檔案
3)在模塊的初始化函式注冊設備對應結構體
4)在模塊的出口注銷設備對應的結構
5)按照對應設備模型:注冊函式需要的引數反向推出應該的結構體成員,
針對雜項模型:
1)定義一個struct miscdevice ,并且填充 minor,fops,name成員
2)定義一個 struct file_operations ,并且填充需要成員
3)在初始化函式中呼叫misc_register注冊一上步實作的 struct miscdevice 結構變數;
4)在出口函式中呼叫misc_deregister注銷一上步實作的 struct miscdevice 結構變數;
5)寫一個應用程式測驗驅動是否按照自己想法運行,對比結果,
最核心的作業在實作 file_operations 的介面函式,這些函式才是真正操作硬體的代碼,其他的都模型代碼,
六、雜項設備示例
6.1. 驅動程式代碼清單
/*驅動代碼 misc.c */
#include <linux/module.h> /* Needed by all modules */
#include <linux/init.h> /* Needed for the module-macros */
#include <linux/fs.h>
#include <linux/miscdevice.h>
static ssize_t misc_read (struct file *pfile,
char __user *buff,
size_t size, loff_t *off)
{
printk(KERN_EMERG "line:%d,%s is call\n",__LINE__,__FUNCTION__);
return 0;
}
static ssize_t misc_write(struct file *pfile,
const char __user *buff,
size_t size, loff_t *off)
{
printk(KERN_EMERG "line:%d,%s is call\n",__LINE__,__FUNCTION__);
return 0;
}
static int misc_open(struct inode *pinode, struct file *pfile)
{
printk(KERN_EMERG "line:%d,%s is call\n",__LINE__,__FUNCTION__);
return 0;
}
static int misc_release(struct inode *pinode, struct file *pfile)
{
printk(KERN_EMERG "line:%d,%s is call\n",__LINE__,__FUNCTION__);
return 0;
}
//檔案操作方法:根據具體設備實作需要的功能
static const struct file_operations misc_fops = {
.read = misc_read,
.write = misc_write,
.release = misc_release,
.open = misc_open,
};
#define DEV_NAME "abc"
#if 1
//C99 標準 新增加的結構體初始化方法,這種可以選其中部分進行初始化,初始化順序不限
static struct miscdevice misc_dev = {
.fops = &misc_fops, /* 設備檔案操作方法 */
.minor = 255, /* 次設備號 */
.name = DEV_NAME, /* 設備名/dev/下的設備節點名 */
};
#else
//c89標準風格的結構體成員初始,只能按順序初始化成員(做了解)
static struct miscdevice misc_dev = {
255, /* 次設備號 */
DEV_NAME, /* 設備名/dev/下的設備節點名 */
&misc_fops /* 設備檔案操作方法 */
};
#endif
static int __init hello_init(void)
{
misc_register(&misc_dev);
printk(KERN_EMERG "misc init \n");
return 0;
}
static void __exit hello_exit(void)
{
misc_deregister(&misc_dev);
printk(KERN_EMERG "Goodbye,misc\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
6.2. 應用程式代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DEV_NAME "/dev/abc"
int main(void)
{
char buf[] = {1, 0, 0, 0};
int i = 0;
int fd;
//打開設備檔案 O_RDWR, O_RDONLY, O_WRONLY,
fd = open(DEV_NAME, O_RDWR);
if(fd < 0)
{
printf("open :%s failt!\r\n", DEV_NAME);
return -1;
}
//寫資料到內核空間
write(fd, buf, 4);
//從內核空間中讀取資料
read(fd, buf, 4);
//關閉設備
close(fd);
return 0;
}
6.3. Makefile 代碼
obj-m := misc.o
KDIR := /home/work/linux-3.5
all:
make -C $(KDIR) M=$(PWD) modules
rm -f *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
arm-linux-gcc app.c -o app
cp -f *.ko app /home/work/rootfs/root
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.markers *.unsigned *.order *~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300549.html
標籤:其他
下一篇:OneNET平臺創建產品
