linux 字符设备驱动
这是一个简单的字符驱动程序,有open, close, read, write 功能,还有 ioctl() 功能
0. 准备
新建 /opt/driver/char2文件夹,在里面创建4个文件: char2.c, test_char2.c, driver_ioctl.h, Makefile
1. char2.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include "driver_ioctl.h"
MODULE_LICENSE("GPL");
static char ker_buf[100];
static int a;
static int dev_open(struct inode* inode, struct file* filep);
static ssize_t dev_read(struct file *filep, char *buf, size_t len, loff_t *off);
static ssize_t dev_write(struct file* filep, const char *buff, size_t len, loff_t *off);
static int dev_release(struct inode* inode, struct file* filep);
static long my_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
static struct file_operations fops =
{
.read = dev_read,
.write = dev_write,
.open = dev_open,
.release = dev_release,
.unlocked_ioctl = my_ioctl,
};
static int char2_init(void)
{
int t = register_chrdev(91, "mydev2", &fops);
if(t < 0)
{
printk(KERN_ALERT "2.=> DEVICE REGISTRATION FAILED.\n");
}
else
{
printk(KERN_ALERT "2.=> DEVICE REGISTERED\n");
}
return 0;
}
static void char2_exit(void)
{
unregister_chrdev(91, "mydev2");
printk(KERN_ALERT "2.=> EXITED.\n");
}
static int dev_open(struct inode* inode, struct file* filep)
{
printk(KERN_ALERT "2.=> DEVICE OPENED\n");
return 0;
}
static ssize_t dev_read(struct file* filep, char *buf, size_t len, loff_t *off)
{
copy_to_user(buf, ker_buf, len);
return len;
}
static ssize_t dev_write(struct file* filep, const char *buf, size_t len, loff_t *off)
{
copy_from_user(ker_buf, buf, len);
ker_buf[len] = 0;
return len;
}
static int dev_release(struct inode *inode, struct file *filep)
{
printk(KERN_ALERT "2.=> DEVICE CLOSED.\n");
return 0;
}
static long my_ioctl(struct file* filep, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case QUERY_GET_VALUE:
copy_to_user((int*)arg, &a, sizeof(int));
break;
case QUERY_SET_VALUE:
copy_from_user(&a, (int*)arg, sizeof(int));
break;
case QUERY_CLEAR_VALUE:
break;
}
return 0;
}
module_init(char2_init);
module_exit(char2_exit);
2. driver_ioctl.h
#include <linux/ioctl.h>
#define QUERY_GET_VALUE _IOR('q', 1, int *)
#define QUERY_CLEAR_VALUE _IO('q', 2)
#define QUERY_SET_VALUE _IOW('q', 3, int*)
3. Makefile
obj-m := char2.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules # make -C /usr/src/kernels/2.6.32-431.el6.i686 M=`pwd` modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
4. test_char2.c
#include <stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <sys/ioctl.h>
#include "driver_ioctl.h"
// compile: gcc -o test_char2 test_char2.c
int main()
{
char buf[100] = "hello";
char rbuf[7] = {0};
int a = 10;
int fd;
fd = open("/dev/mydev2", O_RDWR);
// test read, write
write(fd, buf, strlen(buf));
printf("writing into device\n");
read(fd, rbuf, 6);
printf("read: %s\n", rbuf);
// test ioctl
ioctl(fd, QUERY_SET_VALUE, &a);
printf("value written is: %d\n", a);
a = 0;
printf("let's read value from device\n");
ioctl(fd, QUERY_GET_VALUE, &a);
printf("value of a is: %d\n", a);
return 0;
}
5. 编译
编译 .ko: # make 编译测试程序 test_char2.c : # gcc -o test_char2 test_char2.c
6. 创建字符设备文件
# mknod /dev/mydev2 c 91 1 # chmod a+w /dev/mydev2 mkdod创建设备文件, c 表示字符设备,91是主设备号, 1是次设备号 chmod为设备文件添加写权限, 否则不能向设备写数据。
7. 测试结果:
向内核插入模块: # insmod char2.ko # dmesg # cat /proc/devices ... 91 mydev2 ... 测试设备驱动: [root@centos6 char2]# ./test_char2 writing into device read: hello value written is: 10 let's read value from device value of a is: 10

浙公网安备 33010602011771号