1. 实验目的:
实现一个名字为 blackhole 的设备:从该设备读不到任何数据,却可以写入任意多的数据。
2. 实验环境
系统:Ubuntu 14.04
内核版本:3.13.0-24
3. 实验代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
int scull_major = 0;
int scull_minor = 0;
struct cdev cdev;
#define MAX_SIZE 10
size_t size = 0;
char store[MAX_SIZE];
int scull_open(struct inode *inode, struct file *filp) {
if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) {
size = 0;
}
return 0;
}
int scull_release(struct inode *inode, struct file *filp) {
return 0;
}
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){
ssize_t retval = 0;
if (*f_pos >= size)
goto out;
if (*f_pos + count > size)
count = size - *f_pos;
if (copy_to_user(buf, store + *f_pos, count)) {
retval = -EFAULT;
goto out;
}
*f_pos += count;
retval = count;
out:
return retval;
}
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos){
return count;
}
loff_t scull_llseek(struct file *filp, loff_t off, int whence){
loff_t newpos;
switch(whence) {
case 0:
newpos = off;
break;
case 1:
newpos = filp->f_pos + off;
break;
case 2:
newpos = size + off;
break;
default:
return -EINVAL;
}
if (newpos < 0)
return -EINVAL;
filp->f_pos = newpos;
return newpos;
}
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.release = scull_release,
};
int scull_init_module(void){
int result; dev_t dev = 0;
result = alloc_chrdev_region(&dev, scull_minor, 1, "scull");
scull_major = MAJOR(dev);
if (result < 0) {
printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
return result;
}
cdev_init(&cdev, &scull_fops);
cdev.owner = THIS_MODULE;
cdev.ops = &scull_fops;
result = cdev_add (&cdev, dev, 1);
if (result) {
printk(KERN_WARNING "Error %d adding scull", result);
unregister_chrdev_region(dev, 1);
return result;
}
return 0;
}
void scull_cleanup_module(void){
dev_t dev;
cdev_del(&cdev);
dev = MKDEV(scull_major, scull_minor);
unregister_chrdev_region(dev, 1);
}
module_init(scull_init_module);
module_exit(scull_cleanup_module);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
obj-m := blackhole.o
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/rtc.h>
#include <linux/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int fd;
int i;
char data[256] = {0};
int retval;
fd = open("/dev/scull", O_RDWR);
if (fd == 1) {
perror("open error\n");
exit(-1);
}
printf("open /dev/scull successfully\n");
retval = write(fd, "1234567", 7);
if (retval == -1) {
perror("write error\n");
exit(-1);
}
retval = lseek(fd, 0, 0);
if (retval == -1) {
perror("lseek error\n");
exit(-1);
}
retval = read(fd, data, 10);
if (retval == -1) {
perror("read error\n");
exit(-1);
}
printf("read successfully: %s\n", data);
close(fd);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
4. 实验过程
-
编译驱动程序。
· 把Makefile文件和驱动代码blackhole.c放在一个目录下,在这个目录下执行命令:
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
-
安装驱动模块。
· 执行命令:
sudo insmod blackhole.ko
-
检查设备安装情况,记录设备号。
· 执行命令,并记录设备号:
cat /proc/devices | grep scull
-
在文件系统里创建设备对应的条目
· 执行命令,请注意:命令中的第一个数字 250 应替换为你的系统中设备分配到的 号码,不同系统中分配到的号码可能不一样。:
sudo mknod /dev/scull c 250 0
5.测试设备
· 编译运行testDev.c:
sudo gcc testDev.c -o testDev.o
sudo ./testDev.o
