字元裝置驅動 2

2021-10-01 08:24:33 字數 4707 閱讀 8602

參考:宋寶華 linux裝置驅動開發詳解  嵌入式linux驅動開發教程

開發環境:ubuntu16.04

核心版本:4.13.0-36-generic

主要目的:學習字元裝置的編寫

疑問:

為何cat /dev/globalmem會執行兩次??

file_opration中的函式和open()、 release()、read()、write()呼叫關係是怎樣的,什麼時候呼叫到open()的??

1- **

//cdev_1.c檔案

#include#include#include#include#include#include#include#include#include //包含kmalloc()和kfree()

#include#include 以後的核心使用這個代替#include ,shell下使用uname -r檢視核心版本

#include 為這個

#define globalmem_size 0x1000 /*操作的mem記憶體大小,全域性變數大小4k*/

#define mem_clear 0x1 /*ioctrl命令碼*/

#define globalmem_major 243 /*設定globalmem的主裝置號,檢視已經註冊的避免衝突cat /proc/devices*/

static int globalmem_major = globalmem_major;

/*globalmem結構體*/

struct globalmem_dev

;struct globalmem_dev *globalmem_devp;

/*以下為檔案操作:開啟、釋放、ioctrl、讀寫、定位*/

/*檔案開啟操作*/

int globalmem_open(struct inode *inode, struct file *filp)

/*檔案釋放*/

int globalmem_release(struct inode *inode, struct file *filp)

/*ioctrl操作*/

/*在新的核心中使用long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

或者long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

書中使用的老核心,用的int globalmem_ioctl(struct inode *inodep,...)

新核心改為long 以及去掉第乙個inode引數

*/static long globalmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)//和2.6核心不一樣!!

return 0;

}/*讀函式*/

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)

else

return ret;

}/*寫函式*/

static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)

else

return ret;

}/*檔案定位*/

static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig)

if((unsigned int)offset > globalmem_size)

filp->f_pos = (unsigned int )offset;

ret = filp->f_pos;

break;

/*從當前位置偏移*/

case 1:

if(filp->f_pos + offset < 0)

if((filp->f_pos + offset) > globalmem_size)

filp->f_pos += (unsigned int )offset;

ret = filp->f_pos;

break;

default:

ret = -einval;

break;

} return ret;

}/*檔案操作結構體*/

static const struct file_operations globalmem_fops =

;/*初始化並向核心註冊cdev*/

static void globalmem_setup_cdev(struct globalmem_dev *dev, int index) }

/*裝置驅動模組載入*/

int globalmem_init(void)

else

if(result < 0)

/*申請記憶體*/

globalmem_devp = kmalloc(sizeof(struct globalmem_dev), gfp_kernel);

if(!globalmem_devp)

memset(globalmem_devp,0,sizeof(struct globalmem_dev));

globalmem_setup_cdev(globalmem_devp,0);//向核心註冊cdev

return 0;

fail_malloc:unregister_chrdev_region(devno,1);//解註冊申請的裝置號

return result; }

/*模組解除安裝*/

void globalmem_exit(void)

module_author("lhk");

module_license("dual bsd/gpl");

module_param(globalmem_major, int, s_irugo);

module_init(globalmem_init);

module_exit(globalmem_exit);

2- makefile檔案

ifneq  ($(kernelrelease),)

obj-m:=cdev_1.o

else

kdir := /lib/modules/$(shell uname -r)/build

pwd:=$(shell pwd)

all:

make -c $(kdir) m=$(pwd) modules

clean:

rm -f *.ko *.o *.symvers *.cmd *.cmd.o

endif

3- 驗證

a- 開啟乙個dmesg監視終端

watch "dmesg |tail -20"

b- 將模組載入進核心

insmode globalmem.ko  //將模組編進核心

cat /proc/devices |grep globalmem //檢視是否編進了核心

c- 建立裝置節點

mknod /dev/globalmem c 243 0

mknode用法詳見帖子

ls /dev |grep globalmem //檢視是否建立建立了該裝置節點

d- 讀寫裝置節點

echo "hello world" > /dev/globalmem  //呼叫write()函式,向裝置節點寫,dmesg監視視窗有列印資訊

cat /dev/globalmem   //讀裝置節點,呼叫read()函式,dmesg監視視窗有列印資訊。有如下列印,是正常情況(但是還不理解

詳見帖子分析:

4- 遇到問題

a-  asm/system.h標頭檔案新核心變更為#include

使用uname -r檢視核心版本,版本大於3.3使用#include 替換#include b- kmalloc未包含標頭檔案

包含標頭檔案:#include

c- ioctl新老核心定義不一致

initialization from incompatible pointer type [-werror=incompatible-pointer-types]

initialization from incompatible pointer type

在新的核心中使用long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

或者long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

書中使用的老核心,用的int globalmem_ioctl(struct inode *inodep,struct file *, unsigned int, unsigned long)

新核心改為long 以及去掉第乙個inode引數

5- 總結

學習了簡單字元裝置相關的資料結構及案例編寫

有些東西可能還理解不了,先學會寫,寫多了就理解了。

自己動手,豐衣足食!

字元裝置驅動 2

大部分字元驅動設計三個重要的資料結構 struct file operations struct file struct inode 一 檔案操作 在之前的一篇文章中已經有介紹了如何去生情字元裝置裝置號,但是沒有做任何的工作,也就只能寫乙個不能工作的字元裝置 struct file operatio...

裝置驅動例項 字元裝置驅動

在整個linux裝置驅動學習中,字元裝置驅動較為基礎。通過對它的學習,對裝置驅動進一步加深了解 cdev 結構體struct cdev 講下比較重要的成員變數 dev t dev 定義了32位的裝置號,其中12位是主裝置號,20位是從裝置號。獲取主裝置號 major dev t dev 獲取從裝置號...

字元裝置驅動

字元裝置驅動 概述 塊裝置 字元裝置以及網路裝置中塊裝置和網路裝置一般都會硬體配置完備,對於程式設計師而言,能夠更多操作的就是字元裝置。設定字元裝置的一般步驟 1.初始化硬體 2.定義fops file operations 3.申請cdev,掛載fops 3.加入cdev 函式cdev add 主...