天天看點

linux裝置驅動ioctl,字元裝置驅動ioctl實作使用者層核心層通信

測試代碼實作

memdev.h

#ifndef _MEMDEV_H_

#define _MEMDEV_H_

#include

#ifndef MEMDEV_MAJOR

#define MEMDEV_MAJOR 0

#endif

#ifndef MEMDEV_NR_DEVS

#define MEMDEV_NR_DEVS 2

#endif

#ifndef MEMDEV_SIZE

#define MEMDEV_SIZE 4096

#endif

struct mem_dev

{

char *data;

unsigned long size;

};

#define MEMDEV_IOC_MAGIC 'k'

#define MEMDEV_IOCPRINT _IO(MEMDEV_IOC_MAGIC,0)

#define MEMDEV_IOCGETDATA _IOR(MEMDEV_IOC_MAGIC,1,int)

#define MEMDEV_IOC_MAXNR 3

#endif

memdev.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "memdev.h"

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 ;

}

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

{

return ;

}

long memdev_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)

{

int err = ;

int ret = ;

int ioarg = ;

printk("kernel cmd is : %ld\n",cmd);

switch(cmd)

{

case MEMDEV_IOCPRINT:

printk("CMD MEMDEV_IOCPRINT DONE\n\n");

break;

case MEMDEV_IOCGETDATA:

ioarg = ;

if(copy_to_user((int *)arg,&ioarg,sizeof(int)))

return -EFAULT;

break;

default:

return -EINVAL;

}

return ret;

}

static const struct file_operations mem_fops =

{

.owner = THIS_MODULE,

.open = mem_open,

.release = mem_release,

.unlocked_ioctl = memdev_ioctl,

};

static int memdev_init(void)

{

int result;

int i;

dev_t devno = MKDEV(mem_major,);

if (mem_major)

{

result = register_chrdev_region(devno,,"memdev");

printk("first mem_major is : %ld\n",mem_major);

}

else

{

result = alloc_chrdev_region(&devno,,,"memdev");

mem_major = MAJOR(devno);

printk("second mem_major is : %ld\n",mem_major);

}

if(result < )

return result;

cdev_init(&cdev,&mem_fops);

cdev.owner = THIS_MODULE;

cdev.ops = &mem_fops;

cdev_add(&cdev,MKDEV(mem_major,),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,,sizeof(struct mem_dev));

for(i=;i

{

mem_devp[i].size = MEMDEV_SIZE;

mem_devp[i].data = kmalloc(MEMDEV_SIZE,GFP_KERNEL);

memset(mem_devp[i].data,,MEMDEV_SIZE);

}

return ;

fail_malloc:

unregister_chrdev_region(devno,);

return result;

}

static void memdev_exit(void)

{

cdev_del(&cdev);

kfree(mem_devp);

unregister_chrdev_region(MKDEV(mem_major,),);

}

MODULE_LICENSE("GPL");

module_init(memdev_init);

module_exit(memdev_exit);

Makefile

obj-m += memdev.o

CURRENT_PATH := $(shell pwd)

LINUX_KERNEL := $(shell uname -r)

LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)

all:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules

clean:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

app-ioctl.c

#include

#include

#include

#include

#include "memdev.h"

int main(void)

{

int fd = ;

int cmd;

int arg = ;

char Buf[];

fd = open("/dev/memdev0",O_RDWR);

if(fd < )

{

printf("Open Dev Mem Erro\n");

return -;

}

printf("call memdev_iocprint\n");

cmd = MEMDEV_IOCPRINT;

printf("userspace cmd is : %ld\n",cmd);

if(ioctl(fd,cmd,&arg) < )

{

printf("call cmd MEMDEV_IOCPRINT fail\n");

return -;

}

printf("call MEMDEV_IOCGETDATA\n");

cmd = MEMDEV_IOCGETDATA;

if(ioctl(fd,cmd,&arg) < )

{

printf("call cmd MEMDEV_IOCGETDATA fail\n");

return -;

}

printf("in user space MEMDEV_IOCGETDATA get data is %d\n\n",arg);

close(fd);

return ;

}

編譯memdev,對應的裝置驅動

make

insmod memdev.ko

在dmesg中會有輸出結果init,在/proc/devices中生成對應的裝置驅動号249

建立裝置節點

cat /proc/devices中生成的memdev節點編号249

mknod /dev/memdev0 c 249 0建立裝置節點,并将對應的裝置節點與裝置驅動号進行綁定。當打開該裝置節點進行後續操作時,将會由裝置驅動檔案進行具體實作

編譯app ioctl測試檔案

gcc -o app-ioctl app-ioctl.c

./app-ioctl

正常執行結果會顯示,dmesg也會顯示核心結果

linux 進階字元裝置驅動 ioctl操作介紹 例程分析實作【轉】

轉自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介紹 ioctl控制裝置讀寫資料以及關閉等. 使用者空間函數原型:int ioctl(int f ...

linux裝置驅動第三篇:如何實作一個簡單的字元裝置驅動

在linux裝置驅動第一篇:裝置驅動程式簡介中簡單介紹了字元驅動,本篇簡單介紹如何寫一個簡單的字元裝置驅動.本篇借鑒LDD中的源碼,實作一個與硬體裝置無關的字元裝置驅動,僅僅操作從核心中配置設定的一些記憶體 ...

linux裝置驅動第三篇:如何寫一個簡單的字元裝置驅動?

在linux裝置驅動第一篇:裝置驅動程式簡介中簡單介紹了字元驅動,本篇簡單介紹如何寫一個簡單的字元裝置驅動.本篇借鑒LDD中的源碼,實作一個與硬體裝置無關的字元裝置驅動,僅僅操作從核心中配置設定的一些記憶體 ...

linux裝置驅動第三篇:寫一個簡單的字元裝置驅動

在linux裝置驅動第一篇:裝置驅動程式簡介中簡單介紹了字元驅動,本篇簡單介紹如何寫一個簡單的字元裝置驅動.本篇借鑒LDD中的源碼,實作一個與硬體裝置無關的字元裝置驅動,僅僅操作從核心中分 ...

Linux核心分析(五)----字元裝置驅動實作

原文:Linux核心分析(五)----字元裝置驅動實作 Linux核心分析(五) 昨天我們對linux核心的子系統進行簡單的認識,今天我們正式進入驅動的開發,我們今後的學習為了避免大家沒有硬體的缺陷, ...

Linux字元裝置驅動架構

字元裝置是Linux三大裝置之一(另外兩種是塊裝置,網絡裝置),字元裝置就是位元組流形式通訊的I/O裝置,絕大部分裝置都是字元裝置,常見的字元裝置包括滑鼠.鍵盤.顯示器.序列槽等等,當我們執行ls -l ...

深入了解Linux字元裝置驅動

文章從上層應用通路字元裝置驅動開始,一步步地深入分析Linux字元裝置的軟體層次.組成架構和互動.如何編寫驅動.裝置檔案的建立和mdev原理,對Linux字元裝置驅動有全面的講解.本文整合之前發表的& ...

Linux驅動設計——字元裝置驅動(一)

Linux字元設别驅動結構 cdev結構體 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...

字元裝置驅動、平台裝置驅動、裝置驅動模型、sysfs的比較和關聯

轉載自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 學習Linux裝置驅動開發的過程中自然會遇到字元裝置驅動.平台裝置驅動.裝置驅動模型和sy ...

随機推薦

MySQL索引的Index method中btree和hash的優缺點

MySQL索引的Index method中btree和hash的差別 在MySQL中,大多數索引(如 PRIMARY KEY,UNIQUE,INDEX和FULLTEXT)都是在BTREE中存儲,但使用 ...

開始研究tigase和android用戶端的實作

2015.7.5. 昨晚總算把tigaase7.0的開發環境搭起來了.稍微看了下代碼結構. 主要是auth,db,compnent,cluster,server,xmpp,這幾塊,準備先發點時間看看開 ...

關于WPF中RichTextBox失去焦點後如何保持高亮顯示所選擇的内容

其實很簡單,隻要将容器控件中的附加屬性FocusManager.IsFocusScope設為True就可以了 下面是個簡單的用例:

format格式化和函數

{[name][:][[fill]align][sign][#][0][width][,][.precision][type]}用{ }包裹name命名傳遞給format以命名=值 寫法, 非字典映射 ...

SUSE Enterprise Server 12 SP3 64 設定防火牆開放8080端口

SUSE Enterprise Server 12 SP3 64 設定防火牆開放8080端口 第一種方式: 1.sudo chmod a+w /etc/sysconfig/SuSEfirewall2  ...