1. 程式人生 > >Linux裝置驅動之ioctl控制

Linux裝置驅動之ioctl控制

static int mem_major = MEMDEV_MAJOR;

module_param(mem_major, int, S_IRUGO);

struct mem_dev *mem_devp; /*裝置結構體指標*/

struct cdev cdev;

/*檔案開啟函式*/
int mem_open(struct inode *inode, struct file *filp)
{
struct mem_dev *dev;

/*獲取次裝置號*/
int num = MINOR(inode->i_rdev);

if (num >= MEMDEV_NR_DEVS)
return -ENODEV;
dev = &mem_devp[num];

/*將裝置描述結構指標賦值給檔案私有資料指標*/
filp->private_data = dev;

return 0;
}

/*檔案釋放函式*/
int mem_release(struct inode *inode, struct file *filp)
{
return 0;
}

/*IO操作*/
int memdev_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{

int err = 0;
int ret = 0;
int ioarg = 0;

/* 檢測命令的有效性 */
if (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC)
return -EINVAL;
if (_IOC_NR(cmd) > MEMDEV_IOC_MAXNR)
return -EINVAL;

/* 根據命令型別,檢測引數空間是否可以訪問 */
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
if (err)
return -EFAULT;

/* 根據命令,執行相應的操作 */
switch(cmd) {

/* 列印當前裝置資訊 */
case MEMDEV_IOCPRINT:
printk("<--- CMD MEMDEV_IOCPRINT Done--->\n\n");
break;

/* 獲取引數 */
case MEMDEV_IOCGETDATA:
ioarg = 1101;
ret = __put_user(ioarg, (int *)arg);
break;

/* 設定引數 */
case MEMDEV_IOCSETDATA:
ret = __get_user(ioarg, (int *)arg);
printk("<--- In Kernel MEMDEV_IOCSETDATA ioarg = %d --->\n\n",ioarg);
break;

default:
return -EINVAL;
}
return ret;

}

/*檔案操作結構體*/
static const struct file_operations mem_fops =
{
.owner = THIS_MODULE,
.open = mem_open,
.release = mem_release,
.ioctl = memdev_ioctl,
};

/*裝置驅動模組載入函式*/
static int memdev_init(void)
{
int result;
int i;

dev_t devno = MKDEV(mem_major, 0);

/* 靜態申請裝置號*/
if (mem_major)
result = register_chrdev_region(devno, 2, "memdev");
else /* 動態分配裝置號 */
{
result = alloc_chrdev_region(&devno, 0, 2, "memdev");
mem_major = MAJOR(devno);
}

if (result < 0)
return result;

/*初始化cdev結構*/
cdev_init(&cdev, &mem_fops);
cdev.owner = THIS_MODULE;
cdev.ops = &mem_fops;

/* 註冊字元裝置 */
cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);

/* 為裝置描述結構分配記憶體*/
mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL);
if (!mem_devp) /*申請失敗*/
{
result = - ENOMEM;
goto fail_malloc;
}
memset(mem_devp, 0, sizeof(struct mem_dev));

/*為裝置分配記憶體*/
for (i=0; i < MEMDEV_NR_DEVS; i++)
{
mem_devp[i].size = MEMDEV_SIZE;
mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
memset(mem_devp[i].data, 0, MEMDEV_SIZE);
}

return 0;

fail_malloc:
unregister_chrdev_region(devno, 1);

return result;
}

/*模組解除安裝函式*/
static void memdev_exit(void)
{
cdev_del(&cdev); /*登出裝置*/
kfree(mem_devp); /*釋放裝置結構體記憶體*/
unregister_chrdev_region(MKDEV(mem_major, 0), 2); /*釋放裝置號*/
}

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("GPL");

module_init(memdev_init);
module_exit(memdev_exit);

相關推薦

Linux裝置驅動ioctl控制

static int mem_major = MEMDEV_MAJOR;module_param(mem_major, int, S_IRUGO);struct mem_dev *mem_devp; /*裝置結構體指標*/struct cdev cdev; /*檔案開啟函式*/int mem_open(str

Linux裝置驅動字元裝置驅動---轉

一、linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。 應用程式呼叫的流程框圖: 三種裝置的定義分別如下, 字元裝置:只能一個位元組一個位元組的讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後順序進行。字元裝置是面向流的裝置,常見的字

Linux裝置驅動workqueue----中斷底半部機制

文章為本人學習筆記和總結,如有錯誤,請多多指教; 引言: linux實現中斷底半部的機制主要有tasklet、工作佇列、軟中斷和執行緒化; 本文主要介紹下工作佇列---workqueue 1、工作佇列(workqueue)簡介 Linux中的Workqueue機制就

Linux裝置驅動3.4.2核心下的I2C驅動

框架 1.1 硬體協議簡介 1.2 驅動框架 1.3 bus-drv-dev模型及寫程式 a. 裝置的4種構建方法 詳情參照:linux-3.4.2\Documentation\i2c:instantiating-devices: 以下摘取部分

Linux 裝置驅動 DTS 描述的資源

在linux使用platform_driver_register() 註冊 platform_driver 時, 需要在 platform_driver 的probe() 裡面知道裝置的中斷號, 記憶體地址等資源。 這些資源的描述資訊存放在 resource

Linux裝置驅動中斷---基本程式碼框架

原理已經在上一篇文章中介紹了,這篇文章主要介紹最基本的使用方法,後面的文章有其他使用示例 我使用的硬體是imx6q,原理都一樣。原來的beep引腳是output模式,電路上把它改成了按鍵。 #include <linux/kernel.h>

Linux裝置驅動記憶體對映--mmap--轉

1. 記憶體對映 所謂的記憶體對映就是把實體記憶體對映到程序的地址空間之內,這些應用程式就可以直接使用輸入輸出的地址空間,從而提高讀寫的效率。Linux提供了mmap()函式,用來對映實體記憶體。 在驅動程式中,應用

Linux裝置驅動字元裝置(一)

Linux中裝置驅動的分類 從上圖可以看到Linux系統將各異的裝置分為三大類:字元裝置,塊裝置和網路裝置。核心針對每一類裝置都提供了對應驅動模型架構,包括基本的核心設施和檔案系統介面。 字元裝置:在傳送過程中以字元為單位,一個位元組一個位元組的讀寫,不

Linux裝置驅動字元裝置驅動

一、linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。 應用程式呼叫的流程框圖: 三種裝置的定義分別如下, 字元裝置:只能一個位元組一個位元組的讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後順序進行。字元裝置是面向流的裝置,常見的字元裝置如

Linux裝置驅動button按鍵驅動學習與小結

button按鍵驅動,相對於前面的LED驅動來說。增加了中斷處理以及阻塞與非阻塞方式等新知識點。 先上學習的驅動程式碼。 核心:linux3.0 板子:fl2440 /***************************************************

Linux裝置驅動《字元裝置驅動

    Linux裝置中最大的特點就是裝置操作猶如檔案操作一般,在應用層看來,硬體裝置只是一個裝置檔案。應用程式可以像操作檔案一樣對硬體裝置進行操作,如open(),close(),read(),write()等。     下面是一個字元裝置驅動程式的簡單實現test.c  

linux裝置驅動USB資料傳輸分析(五)

也許,有人會有這樣的疑問: 對於控制傳輸,它不也是基於toggle的糾錯麼,為什麼它就不需要修改後續的包的toggle值呢? 這是因為,控制傳輸的toggle都是從1開始的,刪除掉當前的urb,也不會對後面的發包造成影響. 之後,處理完之後,將無用的td刪除. 跟

linux裝置驅動PCIE驅動開發

#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/signal.h> #include <linux/init.h>

Linux裝置驅動mmap裝置操作(memdev.c字元裝置驅動分析)

from:  1.mmap系統呼叫 void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset); 功能:負責把檔案內容對映到程序的虛擬地址空間,通過對這段記憶體的

linux裝置驅動led子系統

/include/linux/leds.h enumled_brightness{      LED_OFF          = 0,      LED_HALF     = 127,      LED_FULL     = 255, }; led_classd

linux裝置驅動阻塞與非阻塞I/O

先做一下與核心阻塞有關的知識儲備: 1)程序休眠:     程序休眠,簡單的說就是正在執行的程序讓出CPU。休眠的程序會被核心擱置在在一邊,只有當核心再次把休眠的程序喚醒,程序才會會重新在CPU執行。這是核心中的程序排程。一個CPU在同一時間只能有一個程序在執行,微觀序列巨

Linux裝置驅動USB hub驅動(續)

5.2.2:介面驅動中的hub_thread()函式 我們之前在分析usb_hub_init()的程式碼的時候,忽略掉了一部份. 程式碼片段如下所示: int usb_hub_init(void) {    ……     khubd_task = kthread_run(hub_thread, NULL, "

linux裝置驅動USB主機控制器驅動分析 (一)

一:前言 Usb是一個很複雜的系統.在usb2.0規範中,將其定義成了一個分層模型.linux中的程式碼也是按照這個分層模型來設計的.具體的分為 usb裝置,hub和主機控制器三部份.在閱讀程式碼的時候,必須要參考相應的規範.最基本的就是USB2.0的spec.

深入淺出:Linux裝置驅動字元裝置驅動

一、linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。使用驅動程式: 字元裝置:是指只能一個位元組一個位元組讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後資料。字元裝置是面向流的裝置,常見的字元裝置有滑鼠、鍵盤、串列埠、

從零開始驅動發開、linux驅動(二十、linux裝置驅動中的併發控制

本文參考自宋寶華老師的《linux驅動開發詳解》 併發(Concurrency) 指的是多個執行單元同時、 並行被執行, 而併發的執行單元對共享資源(硬體資源和軟體上的全域性變數、 靜態變數等) 的訪問則很容易導致競態(Race Conditions)   只要併發的