编写ioctl例子,用户层可已和内核层通信,即使用_WO/_RO
时间: 2024-03-26 12:41:49 浏览: 86
好的,这里提供一个简单的ioctl例子:
内核层代码:
```c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "testioctl"
#define DEVICE_MAJOR 0
static int device_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device opened\n");
return 0;
}
static int device_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device released\n");
return 0;
}
static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int value = 0;
switch (cmd) {
case 0: // _WO
if (copy_from_user(&value, (int *)arg, sizeof(int)))
return -EFAULT;
printk(KERN_INFO "Set value to %d\n", value);
break;
case 1: // _RO
value = 123;
if (copy_to_user((int *)arg, &value, sizeof(int)))
return -EFAULT;
printk(KERN_INFO "Get value\n");
break;
default:
return -EINVAL;
}
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = device_open,
.release = device_release,
.unlocked_ioctl = device_ioctl,
};
static struct cdev cdev;
static int __init testioctl_init(void)
{
dev_t dev = MKDEV(DEVICE_MAJOR, 0);
int ret;
ret = register_chrdev_region(dev, 1, DEVICE_NAME);
if (ret < 0) {
printk(KERN_ERR "Failed to register device number\n");
return ret;
}
cdev_init(&cdev, &fops);
cdev.owner = THIS_MODULE;
ret = cdev_add(&cdev, dev, 1);
if (ret < 0) {
unregister_chrdev_region(dev, 1);
printk(KERN_ERR "Failed to add device\n");
return ret;
}
printk(KERN_INFO "Device initialized\n");
return 0;
}
static void __exit testioctl_exit(void)
{
cdev_del(&cdev);
unregister_chrdev_region(MKDEV(DEVICE_MAJOR, 0), 1);
printk(KERN_INFO "Device removed\n");
}
module_init(testioctl_init);
module_exit(testioctl_exit);
MODULE_LICENSE("Dual MIT/GPL");
```
用户层代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DEVICE_NAME "/dev/testioctl"
int main(int argc, char **argv)
{
int fd, value, ret;
fd = open(DEVICE_NAME, O_RDWR);
if (fd < 0) {
perror("Failed to open device");
return EXIT_FAILURE;
}
value = 123;
ret = ioctl(fd, 0, &value); // set value
if (ret < 0) {
perror("Failed to set value");
close(fd);
return EXIT_FAILURE;
}
ret = ioctl(fd, 1, &value); // get value
if (ret < 0) {
perror("Failed to get value");
close(fd);
return EXIT_FAILURE;
}
printf("Value is %d\n", value);
close(fd);
return EXIT_SUCCESS;
}
```
编译内核模块:
```
$ make
```
安装内核模块:
```
$ sudo insmod testioctl.ko
```
编译用户层程序:
```
$ gcc -o testioctl testioctl.c
```
运行用户层程序:
```
$ ./testioctl
```
输出:
```
Set value to 123
Get value
Value is 123
```
注意,这里使用了两个ioctl命令,一个是 _WO (0),用于设置值;另一个是 _RO (1),用于获取值。用户层程序先设置值,然后获取值并输出。
阅读全文