首页 > 代码库 > 07 Linux字符驱动---read/write/ioctl

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 }

 

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