驱动程序
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "custom_char_dev"
#define BUFFER_SIZE 1024
static int major_num;
static char buffer[BUFFER_SIZE];
static int pRead = 0;
static int pWrite = 0;
static int bytes_in_buffer = 0;
static int dev_open(struct inode *, struct file *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);
static struct file_operations fops = {
.open = dev_open,
.release = dev_release,
.read = dev_read,
.write = dev_write,
};
static int __init char_dev_init(void) {
major_num = register_chrdev(0, DEVICE_NAME, &fops);
if (major_num < 0) {
printk(KERN_ALERT "Failed to register a major number\n");
return major_num;
}
printk(KERN_INFO "Registered correctly with major number %d\n", major_num);
return 0;
}
static void __exit char_dev_exit(void) {
unregister_chrdev(major_num, DEVICE_NAME);
printk(KERN_INFO "Unregistered correctly\n");
}
static int dev_open(struct inode *inodep, struct file *filep) {
printk(KERN_INFO "Device opened\n");
return 0;
}
static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
int bytes_to_read;
if (bytes_in_buffer == 0) {
printk(KERN_INFO "Buffer is empty\n");
return 0; // Return 0 to indicate end of file (EOF)
}
bytes_to_read = min(len, bytes_in_buffer);
if (copy_to_user(buffer, &buffer[pRead], bytes_to_read) != 0) {
printk(KERN_ALERT "Failed to read from device\n");
return -EFAULT;
}
pRead = (pRead + bytes_to_read) % BUFFER_SIZE;
bytes_in_buffer -= bytes_to_read;
printk(KERN_INFO "Read %d bytes from the device\n", bytes_to_read);
return bytes_to_read;
}
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) {
int space_available = BUFFER_SIZE - bytes_in_buffer;
int bytes_to_write = min(len, space_available);
if (bytes_to_write == 0) {
printk(KERN_ALERT "Buffer is full, cannot write\n");
return -ENOMEM;
}
if (copy_from_user(&buffer[pWrite], buffer, bytes_to_write) != 0) {
printk(KERN_ALERT "Failed to write to device\n");
return -EFAULT;
}
pWrite = (pWrite + bytes_to_write) % BUFFER_SIZE;
bytes_in_buffer += bytes_to_write;
printk(KERN_INFO "Wrote %d bytes to the device\n", bytes_to_write);
return bytes_to_write;
}
static int dev_release(struct inode *inodep, struct file *filep) {
printk(KERN_INFO "Device successfully closed\n");
return 0;
}
module_init(char_dev_init);
module_exit(char_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver with fixed size buffer");
Makefile文件
obj-m += custom_char_dev.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
测试程序
读:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE_FILE "/dev/custom_char_dev"
int main() {
int fd;
char buffer[256];
// 打开设备文件
fd = open(DEVICE_FILE, O_RDONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 读取数据
if (read(fd, buffer, sizeof(buffer)) < 0) {
perror("Failed to read from the device");
close(fd);
return -1;
}
// 打印读取的数据
printf("Data read from device: %s\n", buffer);
// 关闭设备文件
close(fd);
return 0;
}
写:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define DEVICE_FILE "/dev/custom_char_dev"
int main() {
int fd;
char buffer[] = "Hello, device!";
// 打开设备文件
fd = open(DEVICE_FILE, O_WRONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 写入数据
if (write(fd, buffer, strlen(buffer)) < 0) {
perror("Failed to write to the device");
close(fd);
return -1;
}
printf("Data written to device: %s\n", buffer);
// 关闭设备文件
close(fd);
return 0;
}
第二版驱动程序
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#define FIFO_SIZE 32
static char fifo_buffer[FIFO_SIZE];
static int read_pointer = 0;
static int write_pointer = 0;
static int buffer_count = 0;
static DEFINE_MUTEX(fifo_mutex);
static DECLARE_WAIT_QUEUE_HEAD(read_queue);
static DECLARE_WAIT_QUEUE_HEAD(write_queue);
static int custom_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Custom character device opened\n");
return 0;
}
static int custom_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Custom character device closed\n");
return 0;
}
static ssize_t custom_read(struct file *file, char __user *user_buffer, size_t size, loff_t *offset)
{
int bytes_read = 0;
int bytes_to_read = size;
mutex_lock(&fifo_mutex);
while (buffer_count == 0) {
mutex_unlock(&fifo_mutex);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(read_queue, buffer_count > 0))
return -ERESTARTSYS;
mutex_lock(&fifo_mutex);
}
while (bytes_read < size && buffer_count > 0) {
put_user(fifo_buffer[read_pointer], &user_buffer[bytes_read]);
read_pointer = (read_pointer + 1) % FIFO_SIZE;
buffer_count--;
bytes_read++;
}
mutex_unlock(&fifo_mutex);
wake_up_interruptible(&write_queue);
return bytes_read;
}
static ssize_t custom_write(struct file *file, const char __user *user_buffer, size_t size, loff_t *offset)
{
int bytes_written = 0;
int bytes_to_write = size;
mutex_lock(&fifo_mutex);
while (buffer_count == FIFO_SIZE) {
mutex_unlock(&fifo_mutex);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(write_queue, buffer_count < FIFO_SIZE))
return -ERESTARTSYS;
mutex_lock(&fifo_mutex);
}
while (bytes_written < size && buffer_count < FIFO_SIZE) {
get_user(fifo_buffer[write_pointer], &user_buffer[bytes_written]);
write_pointer = (write_pointer + 1) % FIFO_SIZE;
buffer_count++;
bytes_written++;
}
mutex_unlock(&fifo_mutex);
wake_up_interruptible(&read_queue);
return bytes_written;
}
static const struct file_operations custom_fops = {
.owner = THIS_MODULE,
.open = custom_open,
.release = custom_release,
.read = custom_read,
.write = custom_write,
};
static struct miscdevice custom_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "custom_char_dev",
.fops = &custom_fops,
};
static int __init custom_init(void)
{
int ret = misc_register(&custom_misc_device);
if (ret) {
printk(KERN_ERR "Failed to register misc device\n");
return ret;
}
printk(KERN_INFO "Custom character device initialized\n");
return 0;
}
static void __exit custom_exit(void)
{
misc_deregister(&custom_misc_device);
printk(KERN_INFO "Custom character device exited\n");
}
module_init(custom_init);
module_exit(custom_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LLLRY");
MODULE_DESCRIPTION("Custom character device driver");
第二版测试程序
reader.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE_FILE "/dev/my_device"
int main() {
int fd;
char buf[BUF_SIZE];
ssize_t bytes_read;
// 打开设备文件
fd = open(DEVICE_FILE, O_RDONLY);
if (fd < 0) {
perror("Failed to open device file");
return EXIT_FAILURE;
}
// 读取数据
bytes_read = read(fd, buf, sizeof(buf));
if (bytes_read < 0) {
perror("Failed to read from device");
close(fd);
return EXIT_FAILURE;
}
// 打印读取的数据
printf("Read from device: %s\n", buf);
// 关闭设备文件
close(fd);
return EXIT_SUCCESS;
}
writer.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define DEVICE_FILE "/dev/my_device"
int main() {
int fd;
const char *data = "Hello, device!";
ssize_t bytes_written;
// 打开设备文件
fd = open(DEVICE_FILE, O_WRONLY);
if (fd < 0) {
perror("Failed to open device file");
return EXIT_FAILURE;
}
// 写入数据
bytes_written = write(fd, data, strlen(data));
if (bytes_written < 0) {
perror("Failed to write to device");
close(fd);
return EXIT_FAILURE;
}
printf("Wrote to device: %s\n", data);
// 关闭设备文件
close(fd);
return EXIT_SUCCESS;
}
第三版
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#define DEVICE_NAME "FIFODevice"
#define BUFFER_SIZE 1024
static char buffer[BUFFER_SIZE];
static int head = 0;
static int tail = 0;
static unsigned int fifo_count = 0;
static DEFINE_MUTEX(fifo_mutex);
static wait_queue_head_t read_queue;
static wait_queue_head_t write_queue;
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_open,
.release = my_release,
.read = my_read,
.write = my_write,
};
static int __init DevInit(void) {
mutex_init(&fifo_mutex);
init_waitqueue_head(&read_queue);
init_waitqueue_head(&write_queue);
// 注册杂项设备
my_miscdevice = misc_register(MISC_DYNAMIC_MINOR, DEVICE_NAME);
if (my_miscdevice == NULL) {
printk(KERN_ALERT "Failed to register misc device\n");
return -ENODEV;
}
printk(KERN_INFO "Misc device registered as /dev/%s\n", DEVICE_NAME);
return 0;
}
static void __exit DevExit(void) {
// 注销杂项设备
misc_deregister(my_miscdevice);
printk(KERN_INFO "Misc device unregistered\n");
}
static int my_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "Device opened\n");
return 0;
}
static int my_release(struct inode *inode, struct file *file) {
printk(KERN_INFO "Device closed\n");
return 0;
}
static ssize_t my_read(struct file *file, char *buf, size_t count, loff_t *f_pos) {
unsigned long copied;
wait_event_interruptible(read_queue, (fifo_count > 0));
if (signal_pending(current)) {
return -ERESTARTSYS;
}
mutex_lock(&fifo_mutex);
copied = min_t(unsigned int, count, BUFFER_SIZE - head);
if (head < tail && copied > fifo_count) {
copied = fifo_count;
}
memcpy(buf, &buffer[head], copied);
head = (head + copied) % BUFFER_SIZE;
fifo_count -= copied;
mutex_unlock(&fifo_mutex);
printk(KERN_INFO "Read %lu bytes from the device\n", copied);
wake_up_interruptible(&write_queue); // 唤醒写进程
return copied;
}
static ssize_t my_write(struct file *file, const char *buf, size_t count, loff_t *f_pos) {
unsigned long copied;
wait_event_interruptible(write_queue, (fifo_count < (BUFFER_SIZE - 1)));
if (signal_pending(current)) {
return -ERESTARTSYS;
}
mutex_lock(&fifo_mutex);
copied = min_t(unsigned int, count, tail + 1);
memcpy(&buffer[tail], buf, copied);
tail = (tail + copied) % BUFFER_SIZE;
fifo_count += copied;
mutex_unlock(&fifo_mutex);
printk(KERN_INFO "Wrote %lu bytes to the device\n", copied);
wake_up_interruptible(&read_queue); // 唤醒读进程
return copied;
}
module_init(DevInit);
module_exit(DevExit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple FIFO character device with mutex and wait queues");
测试文件
write
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE_NAME "/dev/FIFODevice"
int main() {
int fd;
ssize_t written;
char *message = "Hello, this is a test message!\n";
size_t message_len = strlen(message);
// 打开设备
fd = open(DEVICE_NAME, O_WRONLY);
if (fd < 0) {
perror("Error opening device");
exit(EXIT_FAILURE);
}
// 写入数据
written = write(fd, message, message_len);
if (written < 0) {
perror("Error writing to device");
close(fd);
exit(EXIT_FAILURE);
}
printf("Written %zu bytes to device\n", written);
// 关闭设备
close(fd);
return 0;
}
read
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE_NAME "/dev/FIFODevice"
int main() {
int fd;
ssize_t read_bytes;
char buffer[1024];
// 打开设备
fd = open(DEVICE_NAME, O_RDONLY);
if (fd < 0) {
perror("Error opening device");
exit(EXIT_FAILURE);
}
// 读取数据
read_bytes = read(fd, buffer, sizeof(buffer));
if (read_bytes < 0) {
perror("Error reading from device");
close(fd);
exit(EXIT_FAILURE);
}
// 打印读取的数据
printf("Read %zu bytes from device:\n%s", read_bytes, buffer);
// 关闭设备
close(fd);
return 0;
}
3.2测试程序
写
// write.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define DATA_TO_WRITE "Hello, device!" // 自动写入的数据
#define WRITE_INTERVAL_US 1000000 // 写入间隔,单位:微秒(这里是1秒)
int main() {
int fd;
int write_count = 0;
// 打开设备文件
fd = open(DEVICE_FILE, O_WRONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 循环自动写入数据
while (1) {
// 写入数据
ssize_t bytes_written = write(fd, DATA_TO_WRITE, strlen(DATA_TO_WRITE));
if (bytes_written < 0) {
if (errno == EAGAIN) { // 缓冲区已满,重试写入
continue;
} else {
perror("Failed to write to the device");
close(fd);
return -1;
}
}
// 更新已写入的总字节数
write_count += bytes_written;
printf("Data written to device: %s\n", DATA_TO_WRITE);
// 在此添加适当的延时,以控制写入速率
usleep(WRITE_INTERVAL_US);
}
// 关闭设备文件(永远不会执行到这里)
close(fd);
return 0;
}
读:
// read.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define MAX_BUFFER_SIZE 256
#define READ_INTERVAL_US 1000000 // 读取间隔,单位:微秒(这里是1秒)
int main() {
int fd;
char buffer[MAX_BUFFER_SIZE];
ssize_t bytes_read;
// 打开设备文件
fd = open(DEVICE_FILE, O_RDONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 循环每隔一秒读取数据并打印
while (1) {
// 读取数据
bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read < 0) {
perror("Failed to read from the device");
close(fd);
return -1;
} else if (bytes_read == 0) {
printf("No data available from the device\n");
} else {
// 打印读取到的数据
buffer[bytes_read] = '\0'; // 添加字符串结束符
printf("Data read from device: %s\n", buffer);
}
// 在此添加适当的延时,以控制读取速率
usleep(READ_INTERVAL_US);
}
// 关闭设备文件(永远不会执行到这里)
close(fd);
return 0;
}
3.3
// write.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define MAX_BUFFER_SIZE 256
#define WRITE_INTERVAL_US 1000000 // 写入间隔,单位:微秒(这里是1秒)
int main() {
int fd;
char buffer[MAX_BUFFER_SIZE];
ssize_t bytes_written;
int write_count = 0;
// 打开设备文件
fd = open(DEVICE_FILE, O_WRONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 每隔一秒写入数据直到写满
while (write_count < MAX_BUFFER_SIZE) {
// 构造要写入的数据
sprintf(buffer, "hello device %d", write_count);
// 写入数据
bytes_written = write(fd, buffer, strlen(buffer));
if (bytes_written < 0) {
perror("Failed to write to the device");
close(fd);
return -1;
}
// 更新写入计数
write_count++;
// 在此添加适当的延时,以控制写入速率
usleep(WRITE_INTERVAL_US);
// 每秒报告一次写入信息
printf("Wrote: %s\n", buffer);
}
// 关闭设备文件
close(fd);
// 写入成功后打印信息
printf("Data written to device successfully.\n");
return 0;
}
读:
// read.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define MAX_BUFFER_SIZE 256
#define READ_INTERVAL_US 1000000 // 读取间隔,单位:微秒(这里是1秒)
int main() {
int fd;
char buffer[MAX_BUFFER_SIZE];
ssize_t bytes_read;
// 打开设备文件
fd = open(DEVICE_FILE, O_RDONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 每隔一秒读取数据直到读完
while (1) {
// 读取数据
bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read < 0) {
perror("Failed to read from the device");
close(fd);
return -1;
} else if (bytes_read == 0) {
printf("No data available from the device\n");
} else {
// 打印读取到的数据
buffer[bytes_read] = '\0'; // 添加字符串结束符
printf("Data read from device: %s\n", buffer);
}
// 在此添加适当的延时,以控制读取速率
usleep(READ_INTERVAL_US);
// 每秒报告一次读取信息
printf("Read complete.\n");
}
// 关闭设备文件(永远不会执行到这里)
close(fd);
return 0;
}
3.4
// write.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define MAX_BUFFER_SIZE 256
#define WRITE_INTERVAL_US 1000000 // 写入间隔,单位:微秒(这里是1秒)
int main() {
int fd;
char buffer[MAX_BUFFER_SIZE];
ssize_t bytes_written;
int write_count = 0;
// 打开设备文件
fd = open(DEVICE_FILE, O_WRONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 每隔一秒写入数据直到缓冲区写满
while (write_count < MAX_BUFFER_SIZE) {
// 构造要写入的数据
sprintf(buffer, "hello device %d", write_count);
// 写入数据
bytes_written = write(fd, buffer, strlen(buffer));
if (bytes_written < 0) {
perror("Failed to write to the device");
close(fd);
return -1;
}
// 更新写入计数
write_count++;
// 在此添加适当的延时,以控制写入速率
usleep(WRITE_INTERVAL_US);
// 每秒报告一次写入信息
printf("Wrote: %s\n", buffer);
}
// 关闭设备文件
close(fd);
printf("Buffer is full. Stopped writing.\n");
return 0;
}
// read.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define MAX_BUFFER_SIZE 256
int main() {
int fd;
char buffer[MAX_BUFFER_SIZE];
ssize_t bytes_read;
int read_count = 0;
int ioctl_ret;
// 打开设备文件
fd = open(DEVICE_FILE, O_RDONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 读取数据直到缓冲区为空
while (1) {
// 读取数据
bytes_read = read(fd, buffer, MAX_BUFFER_SIZE);
if (bytes_read < 0) {
perror("Failed to read from the device");
close(fd);
return -1;
} else if (bytes_read == 0) {
// 缓冲区为空,退出循环
break;
}
// 输出读取的数据
printf("Read: %s\n", buffer);
// 清空缓冲区
ioctl_ret = ioctl(fd, IOCTL_CLEAR_BUFFER);
if (ioctl_ret < 0) {
perror("Failed to clear buffer");
close(fd);
return -1;
}
// 更新读取计数
read_count++;
}
// 关闭设备文件
close(fd);
printf("Read complete. Read %d times.\n", read_count);
return 0;
}
// read.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define MAX_BUFFER_SIZE 256
int main() {
int fd;
char buffer[MAX_BUFFER_SIZE];
ssize_t bytes_read;
int read_count = 0;
// 打开设备文件
fd = open(DEVICE_FILE, O_RDONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 读取数据直到缓冲区为空
while (1) {
// 读取数据
bytes_read = read(fd, buffer, MAX_BUFFER_SIZE);
if (bytes_read < 0) {
perror("Failed to read from the device");
close(fd);
return -1;
} else if (bytes_read == 0) {
// 缓冲区为空,退出循环
break;
}
// 输出读取的数据
printf("Read: %s\n", buffer);
// 清空缓冲区
if (lseek(fd, 0, SEEK_SET) < 0) {
perror("Failed to seek to the beginning of the buffer");
close(fd);
return -1;
}
if (write(fd, "", 1) != 1) {
perror("Failed to write to clear the buffer");
close(fd);
return -1;
}
// 更新读取计数
read_count++;
}
// 关闭设备文件
close(fd);
printf("Read complete. Read %d times.\n", read_count);
return 0;
}
// read.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define DEVICE_FILE "/dev/custom_char_dev"
#define MAX_BUFFER_SIZE 256
int main() {
int fd;
char buffer[MAX_BUFFER_SIZE];
ssize_t bytes_read;
int read_count = 0;
// 打开设备文件
fd = open(DEVICE_FILE, O_RDONLY);
if (fd < 0) {
perror("Failed to open the device file");
return -1;
}
// 读取数据直到缓冲区为空
while (1) {
// 读取数据
bytes_read = read(fd, buffer, MAX_BUFFER_SIZE);
if (bytes_read < 0) {
perror("Failed to read from the device");
close(fd);
return -1;
} else if (bytes_read == 0) {
// 缓冲区为空,退出循环
break;
}
// 输出读取的数据
printf("Read: %s\n", buffer);
// 更新读取计数
read_count++;
}
// 关闭设备文件
close(fd);
printf("Read complete. Read %d times.\n", read_count);
return 0;
}