在本章中,我们将编写一个可以接受两个int
型参数和一个char
型参数的驱动,并根据char
的类型——+
或者-
——来计算结果,并最终可以通过read
返回这一结果。
一、驱动程序
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#define DEVICE_NAME "my_calc"
static int result;
static ssize_t my_driver_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
char result_str[16];
int len;
if (*ppos > 0)
return 0;
len = snprintf(result_str, sizeof(result_str), "%d\n", result);
if (count < len)
return -EINVAL;
if (copy_to_user(buf, result_str, len))
return -EFAULT;
*ppos = len;
return len;
}
static ssize_t my_driver_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
uint32_t a, b;
uint8_t symbol;
if (count != sizeof(uint32_t) * 2 + sizeof(uint8_t))
return -EINVAL;
if (copy_from_user(&a, buf, sizeof(uint32_t)))
return -EFAULT;
if (copy_from_user(&b, buf + sizeof(uint32_t), sizeof(uint32_t)))
return -EFAULT;
if (copy_from_user(&symbol, buf + 2 * sizeof(uint32_t), sizeof(uint8_t)))
return -EFAULT;
switch (symbol) {
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
default:
return -EINVAL;
}
return count;
}
static const struct file_operations my_driver_fops = {
.owner = THIS_MODULE,
.read = my_driver_read,
.write = my_driver_write,
};
static struct miscdevice my_driver_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &my_driver_fops,
};
static int __init my_driver_init(void)
{
int ret;
ret = misc_register(&my_driver_device);
if (ret)
pr_err("Failed to register misc device\n");
return ret;
}
static void __exit my_driver_exit(void)
{
misc_deregister(&my_driver_device);
}
module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Author");
MODULE_DESCRIPTION("A simple calculator driver");
二、应用程序
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#define DEVICE_PATH "/dev/my_calc"
int main(int argc, char *argv[])
{
int fd;
int a, b, result;
char symbol;
char buffer[16];
char write_buffer[9];
if (argc != 4) {
fprintf(stderr, "Usage: %s <a> <b> <symbol>\n", argv[0]);
exit(EXIT_FAILURE);
}
a = atoi(argv[1]);
b = atoi(argv[2]);
symbol = argv[3][0];
if (symbol != '+' && symbol != '-') {
fprintf(stderr, "Invalid symbol. Use '+' or '-'.\n");
exit(EXIT_FAILURE);
}
fd = open(DEVICE_PATH, O_RDWR);
if (fd == -1) {
perror("Failed to open device");
exit(EXIT_FAILURE);
}
// 将数据打包到 write_buffer 中
memcpy(write_buffer, &a, sizeof(int));
memcpy(write_buffer + sizeof(int), &b, sizeof(int));
memcpy(write_buffer + 2 * sizeof(int), &symbol, sizeof(char));
// 一次性写入所有数据
if (write(fd, write_buffer, sizeof(write_buffer)) != sizeof(write_buffer)) {
perror("Failed to write data to device");
close(fd);
exit(EXIT_FAILURE);
}
if (read(fd, buffer, sizeof(buffer)) == -1) {
perror("Failed to read result from device");
close(fd);
exit(EXIT_FAILURE);
}
result = atoi(buffer);
printf("%d %c %d = %d\n", a, symbol, b, result);
close(fd);
return 0;
}