日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点

發布時間:2024/8/1 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

加載驅動的指令是:insmod xx.ko

查看驅動的指令是: lsmod

卸載驅動的指令是:rmmod xx

在include/linux/platform_device.h這個文件中定義了平臺驅動注冊和卸載文件函數

platform_driver_register 和 platform_driver_unregister 函數

這個兩個函數參數調用了結構體platform_driver

該結構中包含了一組操作函數和一個 struct device_driver 的對像。在驅動中首先要做的

就是定義 platform_driver 中的函數,并創建這個結構的一個對象實例, 然后在 init()函數中調用

platform_driver_register()向系統注冊驅動。

函數 int (*probe)(struct platform_device *);

主要是進行設備的探測和初始化。例如想調用一個 GPIO,那么首先需要探測這個 GPIO 是

否被占用了,如果被占用了那么初始化失敗,驅動注冊也就失敗了;如果沒有被占用,那么就

申明要占用它。該函數中一般還會添加生成設備節點的函數,如果初始化成功,那么就會需要添加設備節點。

函數 int (*remove)(struct platform_device *);

移除驅動,該函數中一般用于去掉設備節點或者釋放軟硬件資源

void (*shutdown)(struct platform_device *);

int (*suspend)(struct platform_device *, pm_message_t state);

int (*resume)(struct platform_device *);

從字面上就很好理解了,關閉驅動,懸掛(休眠)驅動以及恢復的時候該驅動要做什么

接著的結構體 struct device_driver driver;

主要包含兩個參數,一個是 name 參數,驅動名稱(需要和設備驅動結構體中的 name 參

數一樣,這點很重要);一個是 owner,一般是 THIS_MODULE。

接下來編寫驅動代碼:

#include #include /*驅動注冊的頭文件,包含驅動的結構體和注冊和卸載的函數*/

#include #define DRIVER_NAME "hello_ctl" //這個和前面設備的注冊的hello結構體里面的名字相同

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("TOPEET");

static int hello_probe(struct platform_device *pdv){

printk(KERN_EMERG "\tinitialized\n");

return 0;

}

static int hello_remove(struct platform_device *pdv){

return 0;

}

static void hello_shutdown(struct platform_device *pdv){

;

}

static int hello_suspend(struct platform_device *pdv){

return 0;

}

static int hello_resume(struct platform_device *pdv){

return 0;

}

struct platform_driver hello_driver = {

.probe = hello_probe,

.remove = hello_remove,

.shutdown = hello_shutdown,

.suspend = hello_suspend,

.resume = hello_resume,

.driver = {

.name = DRIVER_NAME, //和devices名稱相同

.owner = THIS_MODULE,

}

};

static int hello_init(void)

{

int DriverState;

printk(KERN_EMERG "HELLO WORLD enter!\n");

DriverState = platform_driver_register(&hello_driver); //然后在模塊入口調用platform_driver_register

printk(KERN_EMERG "\tDriverState is %d\n",DriverState);

return 0;

}

static void hello_exit(void)

{

printk(KERN_EMERG "HELLO WORLD exit!\n");

platform_driver_unregister(&hello_driver);//在函數的出口調用platform_driver_unregister

}

module_init(hello_init);

module_exit(hello_exit);

如果設備和驅動匹配成功就會進入函數 hello_probe 打印“initialized

接著需要編寫一下 Makefile 文件

#!/bin/bash

obj-m += probe_linux_module.o //文件名

#源碼目錄變量,這里用戶需要根據實際情況選擇路徑

KDIR := /home/birate/topeet/iTop4412_Kernel_3.0 #linux源碼目錄

#當前目錄變量

PWD ?= $(shell pwd)

#make命名默認尋找第一個目標

#make -C就是指調用執行的路徑

#$(KDIR)Linux源碼目錄

#$(PWD)當前目錄變量

#modules要執行的操作

all:

make -C $(KDIR) M=$(PWD) modules

#make clean執行的操作是刪除后綴為o的文件

clean:

rm -rf *.o

使用make編譯,生成模塊文件probe_linux_module.ko

然后使用adb push probe_linux_module.ko /data 放到arm系統的/data目錄下

之后加載insmod probe_linux_module.ko

如果沒有錯誤將會打印initialized等內容

之后查看設備

卸載設備

后面我們生成雜項設備節點

雜項設備節點在include/linux/miscdevice.h這個文件中,我們也可以使用cat /proc/misc查看對應的雜項設備

extern int misc_register(struct miscdevice * misc);

雜項設備注冊函數;一般在 probe 中調用,參數是 miscdevice

extern int misc_deregister(struct miscdevice *misc);

雜項設備卸載函數;一般是在 hello_remove 中用于卸載驅動

結構體 miscdevice 中參數很多,下面幾個是常用的。

int .minor;設備號,賦值為 MISC_DYNAMIC_MINOR,這個宏定義可以查到為 10

const char *name;設備名稱

const struct file_operations *fops

file_operations 結構體在頭文件“include/linux/fs.h”中,如下圖所示,使用命令“vim

include/linux/fs.h”打開頭文件。

查找file_operations

struct module *owner;一般是 THIS_MODULE。

int (*open) (struct inode *, struct file *);對應上層的 open 函數,打開文件。

int (*release) (struct inode *, struct file *);對應上層的 close 函數,打開文件操作之后一

般需要關閉。

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);讀函數,上層應用從底層讀取

函數。

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);寫函數,上層應用向底

層傳輸數據。

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);這個函數功能和寫

函數稍微有點重合,但是這個函數占用的內存非常小,主要針對 IO 口的控制

#include #include /*驅動注冊的頭文件,包含驅動的結構體和注冊和卸載的函數*/

#include /*注冊雜項設備頭文件*/

#include /*注冊設備節點的文件結構體*/

#include #define DRIVER_NAME "hello_ctl"

#define DEVICE_NAME "hello_ctl123" //雜項節點名稱

MODULE_LICENSE("Dual BSD/GPL");

static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){

printk("cmd is %d,arg is %d\n",cmd,arg);

return 0;

}

static int hello_release(struct inode *inode, struct file *file){

printk(KERN_EMERG "hello release\n");

return 0;

}

static int hello_open(struct inode *inode, struct file *file){

printk(KERN_EMERG "hello open\n");

return 0;

}

static struct file_operations hello_ops = { //定義file_operations 參數

.owner = THIS_MODULE,

.open = hello_open,

.release = hello_release,

.unlocked_ioctl = hello_ioctl,

};

static struct miscdevice hello_dev = {

.minor = MISC_DYNAMIC_MINOR, //參數 minor 為 MISC_DYNAMIC_MINOR,也就是 10

.name = DEVICE_NAME,//參數 name 為 DEVICE_NAME,也就是 hello_ctl123

.fops = &hello_ops,//參數 fops 為“hello_ops”

};

static int hello_probe(struct platform_device *pdv){

printk(KERN_EMERG "\tinitialized\n");

misc_register(&hello_dev); 向添加 hello_probe 中添加注冊雜項設備的函數 misc_register,如下圖所示,

將 miscdevice 參數定義為 hello_dev

return 0;

}

static int hello_remove(struct platform_device *pdv){

printk(KERN_EMERG "\tremove\n");

misc_deregister(&hello_dev);

return 0;

}

static void hello_shutdown(struct platform_device *pdv){

;

}

static int hello_suspend(struct platform_device *pdv,pm_message_t pmt){

return 0;

}

static int hello_resume(struct platform_device *pdv){

return 0;

}

struct platform_driver hello_driver = {

.probe = hello_probe,

.remove = hello_remove,

.shutdown = hello_shutdown,

.suspend = hello_suspend,

.resume = hello_resume,

.driver = {

.name = DRIVER_NAME,

.owner = THIS_MODULE,

}

};

static int hello_init(void)

{

int DriverState;

printk(KERN_EMERG "HELLO WORLD enter!\n");

DriverState = platform_driver_register(&hello_driver);

printk(KERN_EMERG "\tDriverState is %d\n",DriverState);

return 0;

}

static void hello_exit(void)

{

printk(KERN_EMERG "HELLO WORLD exit!\n");

platform_driver_unregister(&hello_driver);

}

module_init(hello_init);

module_exit(hello_exit);

修改makefile函數

#!/bin/bash

obj-m += devicenode_linux_module.o

#源碼目錄變量,這里用戶需要根據實際情況選擇路徑

KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0

#當前目錄變量

PWD ?= $(shell pwd)

#make命名默認尋找第一個目標

#make -C就是指調用執行的路徑

#$(PWD)當前目錄變量

#modules要執行的操作

all:

make -C $(KDIR) M=$(PWD) modules

#make clean執行的操作是刪除后綴為o的文件

clean:

rm -rf *.o

生成.ko文件

傳到 /data目錄中

加載驅動 在/dev查看設備節點

已經生成了設備節點

卸載 完成

總結

以上是生活随笔為你收集整理的linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。