问题
I am trying to build a kernel module with a simple ioctl function that reads and writes to a chardev. Here is the code for my module:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define MY_MACIG 'G'
#define READ_IOCTL _IOR(MY_MACIG, 0, int)
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
static int major;
static char msg[200];
static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset)
{
printk("I am in device read!\n");
return simple_read_from_buffer(buffer, length, offset, msg, 200);
}
static ssize_t device_write(struct file *filp, const char __user *buff, size_t len, loff_t *off)
{
printk("I am in device write!\n");
if (len > 199)
return -EINVAL;
copy_from_user(msg, buff, len);
msg[len] = '\0';
return len;
}
char buf[200];
static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
int len = 200;
switch(cmd) {
case READ_IOCTL:
trace_printk("read ioctl\n");
printk(KERN_INFO "read ioctl");
copy_to_user((char *)arg, buf, 200);
break;
case WRITE_IOCTL:
trace_printk("write ioctl");
copy_from_user(buf, (char *)arg, len);
break;
default:
return -ENOTTY;
}
return len;
}
static const struct file_operations fops = {
read: device_read,
write: device_write,
unlocked_ioctl: device_ioctl
};
static int __init cdevexample_module_init(void)
{
major = register_chrdev(0, "Arnold-dev", &fops);
if (major < 0) {
printk ("Registering the character device failed with %d\n", major);
return major;
}
printk("Arnold-dev: assigned major: %d\n", major);
printk("create node with mknod /dev/Arnold-dev c %d 0\n", major);
return 0;
}
static void __exit cdevexample_module_exit(void)
{
unregister_chrdev(major, "Arnold-dev");
}
module_init(cdevexample_module_init);
module_exit(cdevexample_module_exit);
MODULE_LICENSE("GPL");
And here is my code in the user space:
#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define MY_MACIG 'G'
#define READ_IOCTL _IOR(MY_MACIG, 0, int)
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
int marker_fd = -1;
int main(){
char buf[200];
int fd = -1;
if ((fd = open("/dev/Arnold-dev", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
perror("open");
return -1;
}
char debugfs[] = "/sys/kernel/debug";
char path[200];
char rd[] = "read in user";
char wr[] = "write in user";
strcpy(path, debugfs);
strcat(path, "/tracing/trace_marker");
marker_fd = open(path, O_WRONLY);
if (marker_fd < 0)
perror("open marker");
if(ioctl(fd, WRITE_IOCTL, "hello world") < 0)
write(marker_fd,wr,strlen(wr));
if(ioctl(fd, READ_IOCTL, buf) < 0)
write(marker_fd,rd, strlen(rd));
printf("message: %s\n", buf);
return 0;
}
The module is built, I can insert it, the init works fine, but the write, read and device_ioctl() functions won't work. The chardev is created, the messages from the init are displayed in dmesg, but anything else is just skipped. The trace is inserted to measure the time between the call for ioctl() and the return from the ioctl(). Is my device_ioctl() function incompatible with unlocked_ioctl? And the same with read and write? I am using XUbuntu with Linux kernel 3.13.0-24-generic.
来源:https://stackoverflow.com/questions/25309661/how-to-use-ioctl-to-read-and-write-to-a-chardev