內(nèi)容企業(yè)推廣河南seo網(wǎng)站多少錢
【Linux】【驅(qū)動】自動創(chuàng)建設備節(jié)點
- 續(xù)
- 驅(qū)動代碼
- 操作指令
- linux端
- 從機端
續(xù)
這里展示了如何自動的方式去創(chuàng)建一個字符類的節(jié)點
下面就是需要調(diào)用到的程序
函數(shù)
void cdev_init(struct cdev *, const struct file_operations *);
第一個參數(shù) 要初始化的 cdev
第二個參數(shù) 文件操作集 cdev->ops = fops; //實際就是把文件操作集寫給 ops
功能 cdev_init()函數(shù)用于初始化 cdev 的成員,并建立 cdev 和 file_operations 之間的連接。
函數(shù)
int cdev_add(struct cdev *, dev_t, unsigned);
第一個參數(shù) cdev 的結構體指針
第二個參數(shù) 設備號
第三個參數(shù) 次設備號的數(shù)量
功能 cdev_alloc()函數(shù)用于動態(tài)申請一個 cdev 內(nèi)存
void cdev_del(struct cdev *);
cdev 的結構體指針
生成設備節(jié)點
字符設備注冊完以后不會自動生成設備節(jié)點。我們需要使用 mknod 命令創(chuàng)建一個設備節(jié)點
格式:mknod 名稱 類型 主設備號 次設備號
mknod /dev/test c 247 0
驅(qū)動代碼
代碼實現(xiàn)的流程
從 hello_init 函數(shù)開始看,
- 注冊設備號,
- 初始化 cdev
- 向系統(tǒng)注冊設備
- 創(chuàng)建 class 類
- 在 class 類下創(chuàng)建設備
從hello_exit 來看
- 注銷設備號
- 刪除設備
- 注銷設備
- 刪除類
#include <linux/init.h>
#include <linux/module.h> //最基本的文件,支持動態(tài)添加和卸載模塊。
#include <linux/fs.h> //包含了文件操作相關 struct 的定義,例如大名鼎鼎的 struct file_operations
#include <linux/kdev_t.h>
#include <linux/cdev.h> //對字符設備結構 cdev 以及一系列的操作函數(shù)的定義。//包含了 cdev 結構及相關函數(shù)的定義。
#include <linux/device.h> //包含了 device、class 等結構的定義#define DEVICE_NUMBER 1 //定義次設備號的個數(shù)
#define DEVICE_SNAME "schrdev" //定義靜態(tài)注冊設備的名稱
#define DEVICE_ANAME "achrdev" //定義動態(tài)注冊設備的名稱
#define DEVICE_MINOR_NUMBER 0 //定義次設備號的起始地址#define DEVICE_CLASS_NAME "chrdev_class" //宏定義類名
#define DEVICE_NODE_NAME "chrdev_test" //宏定義設備節(jié)點的名字static int major_num, minor_num; //定義主設備號和次設備號struct class *class; //定義類
struct device *device; /* 設備 */
struct cdev cdev;//定義一個 cdev 結構體module_param(major_num,int,S_IRUSR); //驅(qū)動模塊傳入普通參數(shù) major_num
module_param(minor_num ,int,S_IRUSR);//驅(qū)動模塊傳入普通參數(shù) minor_numdev_t dev_num;/**
* @description: 打開設備
* @param {structinode} *inode:傳遞給驅(qū)動的 inode
* @param {structfile} *file:設備文件,file 結構體有個叫做 private_data 的成員變量,
* 一般在 open 的時候?qū)?private_data 指向設備結構體。
* @return: 0 成功;其他 失敗
*/
int chrdev_open(struct inode *inode, struct file *file)
{printk("chrdev_open\n");return 0;
}// 設備操作函數(shù)結構體
struct file_operations chrdev_ops = {.owner = THIS_MODULE,.open = chrdev_open};/**
* @description: 驅(qū)動入口函數(shù)
* @param {*}無
* @return {*} 0 成功;其他 失敗
*/
static int hello_init(void)
{int ret;//函數(shù)返回值if(major_num){/*靜態(tài)注冊設備號*/printk("major_num = %d\n",major_num);//打印傳入進來的主設備號printk("minor_num = %d\n",minor_num);//打印傳入進來的次設備號dev_num = MKDEV(major_num,minor_num);//MKDEV 將主設備號和次設備號合并為一個設備號ret = register_chrdev_region(dev_num, DEVICE_NUMBER,DEVICE_SNAME);//注冊設備號if(ret<0){printk("register_chrdev_region error\n");}//靜態(tài)注冊設備號成功,則打印。printk("register_chrdev_region ok\n");}else{/*動態(tài)注冊設備號*/ret = alloc_chrdev_region(&dev_num,DEVICE_MINOR_NUMBER,1, DEVICE_ANAME);if(ret<0){printk("alloc_chrdev_region error\n");}//動態(tài)注冊設備號成功,則打印printk("alloc_chrdev_region ok\n");major_num =MAJOR(dev_num); //將主設備號取出來minor_num = MINOR(dev_num);//將次設備號取出來printk("major_num = %d\n",major_num);//打印傳入進來的主設備號printk("minor_num = %d\n",minor_num);//打印傳入進來的次設備號}// 初始化 cdevcdev.owner = THIS_MODULE;//cdev_init 函數(shù)初始化 cdev 結構體成員變量cdev_init(&cdev, &chrdev_ops);//完成字符設備注冊到內(nèi)核cdev_add(&cdev, dev_num, DEVICE_NUMBER);//創(chuàng)建類class = class_create(THIS_MODULE, DEVICE_CLASS_NAME);// 在 class 類下創(chuàng)建設備device = device_create(class, NULL, dev_num, NULL, DEVICE_NODE_NAME);return 0;
}//drivers for exit
static void hello_exit(void)
{//注銷設備號unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);//刪除設備cdev_del(&cdev);//注銷設備device_destroy(class, dev_num);//刪除類class_destroy(class);printk("gooodbye! \n");}module_init(hello_init);
module_exit(hello_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chris");
下面就是app的代碼
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc,char *argv[])
{int fd;char buf[64] = {0};fd = open("/dev/chrdev_test",O_RDWR); //打開設備節(jié)點if(fd < 0){perror("open error \n");return fd;}//read(fd,buf,sizeof(buf)); //從文件中讀取數(shù)據(jù)放入緩沖區(qū)中close(fd);return 0;
}
操作指令
linux端
arm-buildroot-linux-gnueabihf-gcc -o app app.c
cp app /home/book/nfs_rootfs/
從機端
驅(qū)動卸載掉,再加載新編譯好的的驅(qū)動
rmmod chrdev
insmod chrdev.ko
我們輸入以下命令查看/sys/class 下面是否生成類,
ls /sys/class/chrdev_class/
查看下是否生成了設備節(jié)點
ls /sys/class/
來驗證生成的設備節(jié)點是否可以使用
./app