07 Linux字符驱动---read/write/ioctl

1. mycdev.c

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/cdev.h>
  4 #include <linux/fs.h>
  5 #include <linux/device.h>
  6 #include <linux/err.h>
  7 #include <linux/uaccess.h>
  8 #include <asm-generic/ioctl.h>
  9 #include "cmd.h"
 10
 11 #define MAX 1024
 12
 13 struct mycdev
 14 {
 15     int len;
 16     char kbuf[MAX];
 17     struct cdev cdev;
 18 };
 19
 20 struct mycdev mycdev;
 21 struct class *cls;
 22
 23 int mycdev_open(struct inode *inode, struct file *file)
 24 {
 25     printk("Call mycdev_open()\n");
 26     return 0;
 27 }
 28
 29 ssize_t mycdev_read(struct file *file,char __user *ubuf,size_t size,loff_t *offset)
 30 {
 31     int len;
 32
 33     printk("Call mycdev_read()\n");
 34
 35     if(size >= mycdev.len)
 36         len = mycdev.len;
 37     else
 38         len = size;
 39
 40     if(copy_to_user(ubuf,mycdev.kbuf,len) != 0)
 41     {
 42         printk("copy_to_user() error\n");
 43         return -EFAULT;
 44     }
 45
 46     return len;
 47 }
 48
 49 ssize_t mycdev_write(struct file *file,const char __user *ubuf,size_t size,loff_t *offset)
 50 {
 51     printk("call mycdev_write()\n");
 52
 53     if(size >= MAX)
 54         return -1;
 55
 56     if(copy_from_user(mycdev.kbuf,ubuf,size) != 0)
 57     {
 58         printk("Fail to copy_from_user()");
 59         return -EFAULT;
 60     }
 61
 62     mycdev.len = size;
 63     mycdev.kbuf[size] = ‘\0‘;
 64     printk("write : %s\n",mycdev.kbuf);
 65
 66     return  size;
 67 }
 68
 69 long mycdev_unlocked_ioctl(struct file *file,unsigned int cmd, unsigned long arg)
 70 {
 71     int ret = 0;
 72
 73     switch(cmd)
 74     {
 75         case CMD_CDEV_CLEAN:
 76             memset(mycdev.kbuf,0,MAX);
 77             printk("CMD_CLEN\n");
 78             break;
 79
 80         case CMD_SET_CDEV_LEN:
 81             mycdev.len = arg;
 82             printk("CMD_SET\n");
 83             break;
 84
 85         case CMD_GET_CDEV_LEN:
 86             put_user(mycdev.len,(unsigned long *)arg);
 87             printk("CMD_GET\n");
 88             break;
 89
 90         default:
 91             printk("INvalid\n");
 92             ret = -EINVAL;
 93             break;
 94     }
 95
 96     return ret;
 97 }
 98
 99 struct file_operations fops = {
100     .owner = THIS_MODULE,
101     .open = mycdev_open,
102     .read = mycdev_read,
103     .write = mycdev_write,
104     .unlocked_ioctl = mycdev_unlocked_ioctl,
105 };
106
107 int mycdev_init(void)
108 {
109     int ret = 0;
110     dev_t dev;
111     struct device *device;
112
113     ret = alloc_chrdev_region(&dev, 0, 1, "mycdev");
114     if (ret != 0)
115     {
116         printk("alloc_chrdev_region() error\n");
117         goto err_alloc_chrdev_region;
118     }
119
120     cdev_init(&(mycdev.cdev), &fops);
121
122     ret = cdev_add(&(mycdev.cdev), dev, 1);
123     if (ret != 0)
124     {
125         printk("cdev_add() error\n");
126         goto err_cdev_add;
127     }
128
129     cls = class_create(THIS_MODULE, "mycdev");
130     if (IS_ERR(cls))
131     {
132         ret = PTR_ERR(cls);
133         printk("class_create() error\n");
134         goto err_class_create;
135     }
136
137     device = device_create(cls, NULL, dev, NULL, "mycdev");
138     if (IS_ERR(device))
139     {
140         ret = PTR_ERR(device);
141         printk("device_create() error\n");
142         goto err_device_create;
143     }
144
145     printk("mycdev_init()\n");
146     return 0;
147
148 err_device_create:
149     class_destroy(cls);
150
151 err_class_create:
152     cdev_del(&(mycdev.cdev));
153
154 err_cdev_add:
155     unregister_chrdev_region(dev, 1);
156
157 err_alloc_chrdev_region:
158     return ret;
159 }
160
161 void mycdev_exit(void)
162 {
163     dev_t dev = mycdev.cdev.dev;
164
165     device_destroy(cls, dev);
166     class_destroy(cls);
167     cdev_del(&(mycdev.cdev));
168     cdev_del(&(mycdev.cdev));
169     unregister_chrdev_region(dev, 1);
170
171     printk("mycdev_exit()\n");
172     return;
173 }
174
175 module_init(mycdev_init);
176 module_exit(mycdev_exit);
177
178 MODULE_LICENSE("GPL");
179 MODULE_AUTHOR("GNB");

2. cmd.h

1 #ifndef _CMD_H_
2 #define _CMD_H_
3
4 #define CMD_TYPE            ‘k‘
5 #define CMD_CDEV_CLEAN      _IO(CMD_TYPE,0x10)
6 #define CMD_SET_CDEV_LEN    _IOW(CMD_TYPE,0x11,int)
7 #define CMD_GET_CDEV_LEN    _IOR(CMD_TYPE,0x12,int)
8
9 #endif

3. test.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/types.h>
 4 #include <sys/stat.h>
 5 #include <fcntl.h>
 6 #include <sys/ioctl.h>
 7 #include "cmd.h"
 8
 9 int main(int argc, const char *argv[])
10 {
11     int n;
12     int fd;
13     int pid;
14     int len;
15     char buf[1024];
16     char *string = "hello word\n";
17
18     fd = open("/dev/mycdev_device",O_RDWR);
19     printf("fd = %d\n",fd);
20
21     n = write(fd,string,strlen(string));
22     printf("n = %d\n",n);
23
24     n = read(fd,buf,sizeof(buf));
25     printf("n = %d\n",n);
26
27     ioctl(fd,CMD_CDEV_CLEAN);
28     ioctl(fd,CMD_SET_CDEV_LEN,100);
29     ioctl(fd,CMD_GET_CDEV_LEN,&len);
30     printf("len = %d\n",len);
31
32     return 0;
33 }
时间: 2024-10-26 08:44:31

07 Linux字符驱动---read/write/ioctl的相关文章

Linux字符驱动

学习完了字符驱动,是按照宋宝华的Linux设备驱动开发讲解学习的,代码练习敲了一遍,自己也理解了. 字符驱动主要的就是一些open,close,read,write等操作 通过上层调用到自己写的底层函数 这里写代码片 #include <linux/fs.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/errno.

Linux 字符驱动

char_driver.c 1 #include <linux/module.h> 2 #include <linux/slab.h> //kmalloc 3 #include <linux/cdev.h> //cdev 4 #include <linux/fs.h> //register_chrdev_region 5 #include <linux/device.h> //class_create 6 #include <asm/uac

05 Linux字符驱动---静态注册

1. mycdev.c 1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/cdev.h> 4 #include <linux/fs.h> 5 6 #define MAJOR_NUM 250 7 8 struct mycdev 9 { 10 struct cdev cdev; 11 }; 12 13 int mycdev_open(struct inode *inod

Linux设备驱动中的ioctl

memdev.h #ifndef _MEMDEV_H #define _MEMDEV_H #define MEM_MAGIC 'm' #define MEM_RESTART _IO(MEM_MAGIC, 0)//使用内核提供的宏产生命令, #define MEM_SET _IOW(MEM_MAGIC, 1, int)//改命令向内核传递一个整形的参数 #endif 驱动程序memdev.c #include <linux/module.h> #include <linux/init.h&

08 Linux字符驱动---信号量

1. mycdev.c 1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/cdev.h> 4 #include <linux/fs.h> 5 #include <linux/device.h> 6 #include <linux/err.h> 7 #include <linux/uaccess.h> 8 #include <

linux字符设备驱动

一.字符设备.字符设备驱动与用户空间访问该设备的程序三者之间的关系. 如图,在Linux内核中使用cdev结构体来描述字符设备,通过其成员dev_t来定义设备号(分为主.次设备号)以确定字符设备的唯一性.通过其成员file_operations来定义字符设备驱动提供给VFS的接口函数,如常见的open().read().write()等. 在Linux字符设备驱动中,模块加载函数通过register_chrdev_region( ) 或alloc_chrdev_region( )来静态或者动态获

linux设备驱动第三篇:写一个简单的字符设备驱动

在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存. 下面就开始学习如何写一个简单的字符设备驱动.首先我们来分解一下字符设备驱动都有那些结构或者方法组成,也就是说实现一个可以使用的字符设备驱动我们必须做些什么工作. 1.主设备号和次设备号 对于字符设备的访问是通过文件系统中的设备名称进行的.他们通常位于/dev目录下.如下: [plain] vie

linux设备驱动归纳总结(三):4.ioctl的实现

一.ioctl的简单介绍: 尽管在文件操作结构体"struct file_operations"中有非常多相应的设备操作函数.可是有些命令是实在找不到相应的操作函数. 如CD-ROM的驱动,想要一个弹出光驱的操作,这样的操作并非全部的字符设备都须要的.所以文件操作结构体也不会有相应的函数操作. 出于这种原因,ioctl就有它的用处了----一些没办法归类的函数就统一放在ioctl这个函数操作中.通过指定的命令来实现相应的操作.所以.ioctl函数里面都实现了多个的对硬件的操作.通过应用

深入浅出~Linux设备驱动之字符设备驱动

一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流的设备,常见的字符设备有鼠标.键盘.串口.控制台和LED设备等. 块设备:是指可以从设备的任意位置读取一定长度数据的设备.块设备包括硬盘.磁盘.U盘和SD卡等. 每一个字符设备或块设备都在/dev目录下对应一个设备文件.linux用户程序通过设备文件(或称设备节点)来使用驱动程序操作字符设备和块设备