国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】

這篇具有很好參考價(jià)值的文章主要介紹了【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

經(jīng)過(guò)以下四個(gè)步驟,終于可以開(kāi)始驅(qū)動(dòng)開(kāi)發(fā)了

01.安裝交叉編譯環(huán)境【附下載地址】
02.IMX6ULL燒寫(xiě)Linux系統(tǒng)
03.設(shè)置IMX6ULL開(kāi)發(fā)板與虛擬機(jī)在同一網(wǎng)段
04.IMX6ULL開(kāi)發(fā)板與虛擬機(jī)互傳文件

目錄

一、獲取內(nèi)核、編譯內(nèi)核
二、創(chuàng)建vscode工作區(qū),添加內(nèi)核目錄和個(gè)人目錄
三、了解驅(qū)動(dòng)程序編寫(xiě)流程
四、第一個(gè)驅(qū)動(dòng)程序 - hello驅(qū)動(dòng)
五、IMX6ULL驗(yàn)證hello驅(qū)動(dòng)

一、獲取內(nèi)核、編譯內(nèi)核

1、獲取內(nèi)核文件

獲取Linux內(nèi)核文件,可以從Linux Kernel官網(wǎng)下載,我這里為了跟開(kāi)發(fā)板中的系統(tǒng)一致,避免出現(xiàn)其他問(wèn)題,所以使用的韋東山老師提供的Linux-4.9.88內(nèi)核文件,需要自取

鏈接:https://pan.baidu.com/s/111M2FsgJXAPsQ3ppeVwbFQ
提取碼:p7wp

2、編譯內(nèi)核文件
為什么要編譯內(nèi)核文件,因?yàn)轵?qū)動(dòng)代碼的編譯要基于編譯好的內(nèi)核文件的
在編譯之前,要在~/.bashrc文件下添加兩行內(nèi)容,來(lái)指定編譯的平臺(tái)和工具鏈

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

編譯內(nèi)核步驟:(如果中途報(bào)錯(cuò)了,自行百度一下就行,網(wǎng)上很多解決辦法的,這里就不一一列舉了)

  1. 先刪除之前編譯所生成的文件和配置文件,備份文件等
make mrproper

成功現(xiàn)象:無(wú)內(nèi)容輸出

  1. 設(shè)置內(nèi)核的相關(guān)配置
make 100ask_imx6ull_defconfig

成功現(xiàn)象:

HOSTCC scripts/basic/fixdepHOSTCC scripts/kconfig/conf.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/zconf.lex.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCCscripts /kconfig/zconf.tab.o
HOSTLDscripts/kconfig/conf
#
#configuration written to .config
#
  1. 生成鏡像文件(-j4會(huì)快一些,代表使用4個(gè)核心一起編譯,具體用幾個(gè)核心根據(jù)自己虛擬機(jī)具體情況而定)
make zImage -j4

成功現(xiàn)象:在 內(nèi)核文件/arch/arm/boot/目錄下 生成 zImage 文件,且沒(méi)有報(bào)錯(cuò)

  1. 生成設(shè)備樹(shù)(這一步也做一下,很快的,雖然我們用不到,就跟著步驟來(lái)嘛)
make dtbs

成功現(xiàn)象:輸出幾行內(nèi)容,無(wú)報(bào)錯(cuò)

  1. 在家目錄下新建 nfs_rootfs 目錄,將鏡像文件、生成的設(shè)備樹(shù)拷貝其目錄下 (可不做)
cp arch/arm/boot/zImage ~/nfs_rootfs
cp arch/arm/boot/dts/100ask_imx6ull-14x14.dtb ~/nfs_rootfs
  1. 編譯內(nèi)核模塊
make modules

成功現(xiàn)象:輸出很多.o文件,最后輸出一些.ko文件,無(wú)報(bào)錯(cuò)


二、配置vscode,添加內(nèi)核目錄和個(gè)人目錄

  1. 使用vscode打開(kāi)linux-4.9.88內(nèi)核目錄,點(diǎn)擊左上角 “文件” ,“將工作區(qū)另存為”,選擇家目錄下,隨便起個(gè)名字
  2. 使用vscode打開(kāi)自己要編寫(xiě)驅(qū)動(dòng)的文件目錄,右鍵自己的文件夾,選擇“ 將文件夾添加到工作區(qū)”,選擇自己創(chuàng)建的那個(gè)工作區(qū)
  3. 至此就可以在vscode同一個(gè)工作區(qū)下看到自己的驅(qū)動(dòng)文件和linux內(nèi)核文件了,方便后續(xù)獨(dú)照內(nèi)核文件內(nèi)容

【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】,Linux驅(qū)動(dòng)開(kāi)發(fā)【IMX6ULL】,驅(qū)動(dòng)開(kāi)發(fā),linux驅(qū)動(dòng),第一個(gè)驅(qū)動(dòng)程序,IMX6ULL,insmod

  1. 在.vscode 下的c_cpp_properties.json 文件中設(shè)置工作路徑
"/home/me/Linux-4.9.88/tools/virtio",
"/home/me/Linux-4.9.88/include/**",
"/home/me/Linux-4.9.88/include/linux/**",
"/home/me/Linux-4.9.88/arch/arm/include/**",
"/home/me/Linux-4.9.88/arch/arm/include/generated/**"

三、了解驅(qū)動(dòng)程序編寫(xiě)流程

1. 先看內(nèi)核目錄下原有的驅(qū)動(dòng)是怎么寫(xiě)的
打開(kāi)Linux-4.9.88/drivers/char目錄(看名字就猜到該目錄下存放應(yīng)該是字符驅(qū)動(dòng)代碼
發(fā)現(xiàn)有個(gè) ds1602.c ,打開(kāi)看看它是怎么寫(xiě)的(因?yàn)槲覍W(xué)過(guò)了,選擇這個(gè)文件,展示主要代碼,有助于入門(mén)理解)

#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/capability.h>
#include <linux/init.h>
#include <linux/mutex.h>

#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/therm.h>

static DEFINE_MUTEX(ds1620_mutex);
static const char *fan_state[] = { "off", "on", "on (hardwired)" };

.....
..... 省略
.....

static int __init ds1620_init(void)
{
	int ret;
	struct therm th, th_start;

	if (!machine_is_netwinder())
		return -ENODEV;

	ds1620_out(THERM_RESET, 0, 0);
.....
..... 省略
.....

static int ds1620_open(struct inode *inode, struct file *file)
{
	return nonseekable_open(inode, file);
}

.....
..... 省略
.....

static ssize_t ds1620_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
{
	signed int cur_temp;
	signed char cur_temp_degF;

	cur_temp = cvt_9_to_int(ds1620_in(THERM_READ_TEMP, 9)) >> 1;

	/* convert to Fahrenheit, as per wdt.c */
	cur_temp_degF = (cur_temp * 9) / 5 + 32;

	if (copy_to_user(buf, &cur_temp_degF, 1))
		return -EFAULT;

	return 1;
}


.....
..... 省略
.....

static const struct file_operations ds1620_fops = {
	.owner		= THIS_MODULE,
	.open		= ds1620_open,
	.read		= ds1620_read,
	.unlocked_ioctl	= ds1620_unlocked_ioctl,
	.llseek		= no_llseek,
};

.....
..... 省略
.....

static void __exit ds1620_exit(void)
{
#ifdef THERM_USE_PROC
	remove_proc_entry("therm", NULL);
#endif
	misc_deregister(&ds1620_miscdev);
}

module_init(ds1620_init);
module_exit(ds1620_exit);

MODULE_LICENSE("GPL");

2. 驅(qū)動(dòng)程序主要構(gòu)成(主要是的前面四個(gè))
· file_operations 結(jié)構(gòu)體 : 為系統(tǒng)調(diào)用提供驅(qū)動(dòng)程序入口的結(jié)構(gòu)體
· module_init : 定義驅(qū)動(dòng)模塊的入口函數(shù)
· module_exit : 定義驅(qū)動(dòng)模塊的退出函數(shù)
· MODULE_LICENSE(“GPL”) : 聲明模塊許可證,指明這是GNU General Public License的任意版本,
?????????????????????????????????????????????????????否則在加載此模塊時(shí),會(huì)收到內(nèi)核被污染 “kernel tainted” 的警告

· ds1620_init :ds1602初始化函數(shù)
· ds1620_open : 打開(kāi)ds1602設(shè)備函數(shù)
· ds1620_read : 讀ds1602設(shè)備函數(shù)
· ds1620_exit : ds1602退出驅(qū)動(dòng)函數(shù)

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

3. 驅(qū)動(dòng)程序?qū)崿F(xiàn)過(guò)程及調(diào)用原理
· module_init 指定驅(qū)動(dòng)入口函數(shù)
· 設(shè)備對(duì)象通過(guò) struct file_operations 結(jié)構(gòu)體定義
· 入口函數(shù)中調(diào)用 register_chrdev 函數(shù),傳入注冊(cè)定義好的驅(qū)動(dòng)設(shè)備變量,生成設(shè)備號(hào)
· 在開(kāi)發(fā)板上通過(guò) insmod 命令將編譯好的驅(qū)動(dòng)模塊(.ko文件,要從虛擬機(jī)傳到板子上哦)載入內(nèi)核
· 通過(guò)應(yīng)用程序可以對(duì)設(shè)備進(jìn)行讀寫(xiě)等操作,讀寫(xiě)等操作通過(guò)系統(tǒng)調(diào)用 register_chrdev 結(jié)構(gòu)體中指定的驅(qū)動(dòng)模塊讀寫(xiě)等函數(shù)來(lái)實(shí)現(xiàn)
· close設(shè)備時(shí),系統(tǒng)調(diào)用 module_exit 指定的驅(qū)動(dòng)模塊退出函數(shù)

以上便是驅(qū)動(dòng)程序?qū)崿F(xiàn)過(guò)程及應(yīng)用程序調(diào)用驅(qū)動(dòng)程序的原理(按照個(gè)人理解寫(xiě)的,大概是這么個(gè)流程,有不恰當(dāng)?shù)牡胤綒g迎指出)

四、第一個(gè)驅(qū)動(dòng)程序 - hello驅(qū)動(dòng)

1. 在個(gè)人目錄下新建 hello_drv.c 文件
2. 照葫蘆畫(huà)瓢,把上面 ds1602 用到的
頭文件**都復(fù)制過(guò)來(lái)
3. 繼續(xù)照葫蘆畫(huà)瓢編寫(xiě) file_operations 結(jié)構(gòu)體**

static const struct file_operations hello_drv = {
    .owner 		= THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
	.release    = hello_release,
};

假裝我們的驅(qū)動(dòng)也可以讀、寫(xiě),當(dāng)然也必須有open和release(就是close)
當(dāng)然 .owner = THIS_MODULE, 也必須有,原因見(jiàn)博客https://blog.csdn.net/a954423389/article/details/6101369

4. 研究file_operations結(jié)構(gòu)體
每個(gè)函數(shù)都有對(duì)應(yīng)的模板,可不是亂寫(xiě)的,因?yàn)檫@些函數(shù)組中都會(huì)被系統(tǒng)調(diào)用,參數(shù)都是固定的,可以按住ctrl鍵,用鼠標(biāo)點(diǎn)擊file_operations,跳轉(zhuǎn)到該結(jié)構(gòu)體定義處,可以看到每個(gè)函數(shù)指針的形式
【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】,Linux驅(qū)動(dòng)開(kāi)發(fā)【IMX6ULL】,驅(qū)動(dòng)開(kāi)發(fā),linux驅(qū)動(dòng),第一個(gè)驅(qū)動(dòng)程序,IMX6ULL,insmod

5. 照葫蘆畫(huà)瓢實(shí)現(xiàn)hello_read、hello_write、hello_open、hello_release函數(shù)

/*養(yǎng)成好習(xí)慣,驅(qū)動(dòng)程序都加static修飾*/
static int hello_open (struct inode *node, struct file *filp)
{
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);
	return 0;
}

static ssize_t hello_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{
	printk("hello_read\n");
	return size;  //返回讀取字節(jié)數(shù)
}

static ssize_t hello_write (struct file *filp, const char *buf, size_t size, loff_t *offset)
{
	printk("hello_write\n");
	return size;  //返回寫(xiě)入字節(jié)數(shù)
}

static int hello_release (struct inode *node, struct file *filp)
{
	printk("hello_release\n");
	return 0;
}

6. 編寫(xiě)hello驅(qū)動(dòng)的入口函數(shù)、出口函數(shù)
入口函數(shù)需要用到 register_chrdev 函數(shù)
出口函數(shù)(退出函數(shù))需要用到 unregister_chrdev 函數(shù),但是 ds1602.c 中沒(méi)有這兩個(gè)函數(shù)
沒(méi)關(guān)系,我們?cè)趘scode中搜索 register_chrdev, 隨便點(diǎn)一個(gè)看一下,研究一下用法(實(shí)在看不懂百度一下哈哈)
也可以用linux命令查找(在內(nèi)核的drivers/char目錄下查找)

grep "register_chrdev" * -nwr

【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】,Linux驅(qū)動(dòng)開(kāi)發(fā)【IMX6ULL】,驅(qū)動(dòng)開(kāi)發(fā),linux驅(qū)動(dòng),第一個(gè)驅(qū)動(dòng)程序,IMX6ULL,insmod
我們用vscode找一下

【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】,Linux驅(qū)動(dòng)開(kāi)發(fā)【IMX6ULL】,驅(qū)動(dòng)開(kāi)發(fā),linux驅(qū)動(dòng),第一個(gè)驅(qū)動(dòng)程序,IMX6ULL,insmod
發(fā)現(xiàn) register_chrdev 函數(shù)需要三個(gè)參數(shù)
第一個(gè)參數(shù)是主設(shè)備號(hào),0代表動(dòng)態(tài)分配
第二個(gè)參數(shù)是設(shè)備的名字(自定義)
第三個(gè)參數(shù)是struct file_operations結(jié)構(gòu)體類(lèi)型的指針,代表申請(qǐng)?jiān)O(shè)備的操作函數(shù)

同理,出口函數(shù) unregister_chrdev
第一個(gè)參數(shù)是設(shè)備號(hào)
第二個(gè)參數(shù)是設(shè)備名稱

照葫蘆畫(huà)瓢開(kāi)始寫(xiě)

/*入口函數(shù)*/
static int major;
static int hello_init(void)
{
	/*返回設(shè)備號(hào),定義設(shè)備名稱為hello_drv*/
	major = register_chrdev(0,"hello_drv",&hello_drv);
	return 0;
}

/*退出函數(shù)*/
static int hello_exit(void)
{
	unregister_chrdev(major,"hello_drv");
	return 0;
}	

7. module_init 、module_exit和聲明許可證

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

整個(gè) hello_drv.c 代碼

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/capability.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/therm.h>

static int major;

static int hello_open (struct inode *node, struct file *filp)
{
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);
	return 0;
}

static ssize_t hello_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{
	printk("hello_read\n");
	return size;  //返回讀取字節(jié)數(shù)
}

static ssize_t hello_write (struct file *filp, const char *buf, size_t size, loff_t *offset)
{
	printk("hello_write\n");
	return size;  //返回寫(xiě)入字節(jié)數(shù)
}

static int hello_release (struct inode *node, struct file *filp)
{
	printk("hello_release\n");
	return 0;
}

/*1.定義 file_operations 結(jié)構(gòu)體*/
static const struct file_operations hello_drv = {
    .owner 		= THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
	.release    = hello_release,
};


/*2.register_chrdev*/

/*3.入口函數(shù)*/
static int hello_init(void)
{
	//設(shè)備號(hào)
	major = register_chrdev(0,"hello_drv",&hello_drv);
	return 0;
}

/*4.退出函數(shù)*/
static int hello_exit(void)
{
	//卸載驅(qū)動(dòng)
	unregister_chrdev(major,"hello_drv");
	return 0;
}	

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

8. 編寫(xiě)Makefile

不多說(shuō),直接上代碼

KERN_DIR = /home/me/Linux-4.9.88

PWD ?= $(shell KERN_DIR)

all:	
	make -C $(KERN_DIR) M=$(PWD) modules
	#$(CROSS_COMPILE)gcc -o hello_test hello_test.c
clean:
	make -C $(KERN_DIR) M=$(PWD) modules clean
	rm -rf modules.order
	rm -f hello_drv

obj-m += hello_drv.o

KERN_DIR = /home/me/Linux-4.9.88 : 編譯程序的依賴目錄

9. make一下,生成.ko文件

me@ubuntu:~/Linux_ARM/IMX6ULL/hello_driver$ ls
hello_drv.c  hello_drv.ko  hello_drv.mod.c  hello_drv.mod.o  hello_drv.o  
hello_test  hello_test.c  Makefile  modules.order  Module.symvers

主要就是.ko文件,就是加載到內(nèi)核里的驅(qū)動(dòng)模塊文件


五、IMX6ULL驗(yàn)證hello驅(qū)動(dòng)

1. 將虛擬機(jī)編譯生成的.ko文件拷貝到IMX6ULL開(kāi)發(fā)板上
這步操作需要虛擬機(jī)和開(kāi)發(fā)板在同一網(wǎng)段下,可以借鑒以下兩篇博客
03.設(shè)置IMX6ULL開(kāi)發(fā)板與虛擬機(jī)在同一網(wǎng)段
04.IMX6ULL開(kāi)發(fā)板與虛擬機(jī)互傳文件
我采用的是NFS掛載的方式

mount -t nfs -o nolock,vers=3 192.168.1.200:/home/me/Linux_ARM/IMX6ULL/hello_driver /mnt

【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】,Linux驅(qū)動(dòng)開(kāi)發(fā)【IMX6ULL】,驅(qū)動(dòng)開(kāi)發(fā),linux驅(qū)動(dòng),第一個(gè)驅(qū)動(dòng)程序,IMX6ULL,insmod
如果出現(xiàn)報(bào)錯(cuò)

failed: Device or resource busy

執(zhí)行

unmount /mnt

2.加載內(nèi)核
執(zhí)行命令加載內(nèi)核

insmod hello_drv.ko
[root@100ask:/mnt]# insmod hello_drv.ko 
[   80.794911] hello_drv: loading out-of-tree module taints kernel.
[root@100ask:/mnt]#

顯示已載入系統(tǒng)的模塊

lsmod

【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】,Linux驅(qū)動(dòng)開(kāi)發(fā)【IMX6ULL】,驅(qū)動(dòng)開(kāi)發(fā),linux驅(qū)動(dòng),第一個(gè)驅(qū)動(dòng)程序,IMX6ULL,insmod
查看 hello_drv.ko 驅(qū)動(dòng)模塊的設(shè)備號(hào)

cat /proc/devices
226 drm
240 hello_drv
241 adxl345
242 spidevx
243 irda
244 dht11

可以看到hello驅(qū)動(dòng)的設(shè)備號(hào)是240

3.生成設(shè)備節(jié)點(diǎn)

mknod /dev/hello c 240 0

/dev/hello : 生成設(shè)備節(jié)點(diǎn)的名稱
c :說(shuō)明是字符設(shè)備
240 : 主設(shè)備號(hào)
0 : 子設(shè)備號(hào)(不指定子設(shè)備號(hào),為0)

這時(shí)候查看hello設(shè)備也可以用下面的命令

[root@100ask:/mnt]# ls /dev/hello -l
crw-r--r-- 1 root root 240, 0 Jan  1 11:34 /dev/hello

4.編寫(xiě)應(yīng)用程序驗(yàn)證驅(qū)動(dòng)

PS:在第四節(jié)第8小節(jié)中,將 $(CROSS_COMPILE)gcc -o hello_test hello_test.c 這一行注釋去掉

編寫(xiě) hello_test.c 應(yīng)用程序

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int len;
    char read_buf[10];

    if(argc < 2){
        printf("please input  at least 2 args\n");
        printf("%s <dev> [string]\n", argv[0]);
        return -1;
    }

    /*open*/
    int fd;
    fd = open(argv[1], O_RDWR);
    if(fd < 0){
        printf("open failed\n");
        return -2;
    }

    /*read*/
    if(argc == 2){
        read(fd, read_buf, 10);    //調(diào)用read函數(shù),只為了觸發(fā)系統(tǒng)調(diào)用hello驅(qū)動(dòng)的read函數(shù)
        printf("read operation \n");
    }

    /*write*/
    if(argc == 3){
        len = write(fd, argv[2], strlen(argv[2]));   //調(diào)用write函數(shù),只為了觸發(fā)系統(tǒng)調(diào)用hello驅(qū)動(dòng)的write函數(shù)
        printf("write length = %d \n", len);
    }

    close(fd);

    return 0;
}

該程序的使用方式:

./hello_test   /dev/hello  123abc     兩個(gè)參數(shù):模擬寫(xiě)操作
./hello_test   /dev/hello             一個(gè)參數(shù):模擬讀操作

/dev/hello 是我們要打開(kāi)的設(shè)備名稱,在應(yīng)用程序中,使用 open 函數(shù)打開(kāi),使用 close 函數(shù)關(guān)閉

如果打開(kāi)成功,則系統(tǒng)會(huì)調(diào)用 hello 驅(qū)動(dòng)的 open 函數(shù),我們就會(huì)看到相應(yīng)的打印信息(打印出當(dāng)前文件名,函數(shù)名,行數(shù))

static int hello_open (struct inode *node, struct file *filp)
{
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);
	return 0;
}

注意驅(qū)動(dòng)程序中使用的都是printk函數(shù),該函數(shù)是內(nèi)核調(diào)用的,想要在開(kāi)發(fā)板的串口打印信息中看到輸出,需要執(zhí)行以下命令

echo "7 4 1 7" > /proc/sys/kernel/printk

測(cè)試驅(qū)動(dòng)寫(xiě)操作,成功?。?!

[root@100ask:/mnt]# ./hello_test /dev/hello 
[  499.512588] hello_open
[  499.516872] /home/me/Linux_ARM/IMX6ULL/hello_driver/hello_drv.c hello_open 28
[  499.525082] hello_read
read operation [  499.528427] hello_release

[root@100ask:/mnt]# 

測(cè)試驅(qū)動(dòng)讀操作,成功!?。?mark hidden color="red">文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-735606.html

[root@100ask:/mnt]# ./hello_test /dev/hello abc123
[  500.725340] hello_open
[  500.727762] /home/me/Linux_ARM/IMX6ULL/hello_driver/hello_drv.c hello_open 28
[  500.736217] hello_write
write length = 6 [  500.739735] hello_release

[root@100ask:/mnt]# 

【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】,Linux驅(qū)動(dòng)開(kāi)發(fā)【IMX6ULL】,驅(qū)動(dòng)開(kāi)發(fā),linux驅(qū)動(dòng),第一個(gè)驅(qū)動(dòng)程序,IMX6ULL,insmod文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-735606.html

到了這里,關(guān)于【IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)】05.IMX6ULL驅(qū)動(dòng)開(kāi)發(fā)_編寫(xiě)第一個(gè)hello驅(qū)動(dòng)【熬夜肝】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包