自行实现ioctl

在上一个hello模块的安装卸载后,我们来实行一下ioctl。最终的目的是实现控制继电器的开启和关闭
hello.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h> // cdev_add cdev_init
#include <linux/kdev_t.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h> // struct file_operations

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#include "msg.h"
#define HELLO_MAJOR 10
#define HELLO_MINJOR 99
MODULE_LICENSE("Dual BSD/GPL");
//MODULE_LICENSE("GPL2");
int open(struct inode *inode1, struct file *filep) {
    printk(KERN_ALERT "open success\n");
    gpio_direction_output(4,0);
    mdelay(500);
    gpio_direction_output(4,1);
    return 0;
}
int release(struct inode *inode, struct file *filep) {
    printk(KERN_ALERT "release success\n");
    return 0;
}

int ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
    switch(cmd)//对命令进行判定
    {
        case MODLD:
            printk(KERN_ALERT"LOW\n");
            break;
        case CMD_LEVEL:
            break;

    }
    return 0;
}

struct file_operations myfops = {
    .owner = THIS_MODULE, .open = open, .release = release,.unlocked_ioctl=ioctl, };

struct cdev c_dev;
struct class *myclass=NULL;
void cleanup(int a, int b) {
    dev_t devno;
    devno = MKDEV(HELLO_MAJOR, HELLO_MINJOR);
    if (b == 1) {
        device_destroy(myclass, devno);
    }
    if (a == 1) {
        cdev_del(&c_dev);
    }
    unregister_chrdev_region(devno, 1);
}

static int hello_init(void) {
    int ret;
    int device_creat;
    int dev_add;
    int devno;
    gpio_request(4,"JDQ");

    //c_dev=cdev_alloc();
   // myclass = class_create(THIS_MODULE, "hello");
    printk(KERN_ALERT "hello world\n");
    devno = MKDEV(HELLO_MAJOR, HELLO_MINJOR);
    ret = register_chrdev_region(0, 1, "hello");
    if (ret < 0) {
        printk(KERN_ALERT "chardev_region filed\n");
        return -1;
    }
    // cdev_add(c_dev,devon,1);
    if (NULL == device_create(myclass, NULL, HELLO_MAJOR, NULL, "hello")) {
        goto cleanup1;
    }
    device_creat = 1;
    cdev_init(&c_dev, &myfops);
    c_dev.owner = THIS_MODULE;
    c_dev.ops = &myfops;
    ret = cdev_add(&c_dev, devno, 1);
    if (ret < 0) {
        printk(KERN_ALERT "cdev_add filed\n");
        return -1;
    }
    dev_add = 1;

    return 0;
cleanup1:
    cleanup(dev_add, device_creat);
    return -1;
}

static void hello_exit(void) {
    printk(KERN_ALERT "goodbay world\n");
    cleanup(1, 1);
}

module_init(hello_init);
module_exit(hello_exit);

msg。h

#ifndef MSG_H
#define MSG_H
#include <linux/ioctl.h>
#define MAGIC 'c'
#define CMD_PIN_LOW 0
#define CMD_PIN_HIGH 1
#define CMD_PIN_INPUT 1
#define CMD_PIN_OUTPUT 0

#define MODLD _IOW(MAGIC,0,int)
#define CMD_LEVEL _IOW(MAGIC,1,int)
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ioctl实现原理涉及到用户空间和内核空间之间的交互。下面是ioctl的大致实现原理: 1. 用户空间调用ioctl函数:用户程序通过ioctl函数调用发起ioctl请求,需要提供设备文件描述符、请求码以及相关的参数。 2. 内核空间处理ioctl请求:当用户空间调用ioctl函数时,操作系统会将控制权转移到内核空间,并在内核中找到相应的设备驱动程序。 3. 设备驱动程序处理ioctl请求:内核中的设备驱动程序根据ioctl传递的请求码,执行相应的操作。它可能会读取或修改设备的状态、配置设备参数等。 4. 内核空间返回处理结果:设备驱动程序执行完ioctl操作后,将结果返回给内核空间。 5. 用户空间接收处理结果:操作系统将处理结果传递回用户空间,并返回给调用ioctl函数的用户程序。 具体实现原理可以分为以下几个步骤: - 用户调用ioctl函数时,将参数传递到内核中,包括设备文件描述符、请求码和参数。 - 内核中的系统调用接收到用户空间的请求,将控制权转移到内核空间。 - 内核根据设备文件描述符找到相应的设备驱动程序,并根据请求码执行相应的操作。 - 设备驱动程序根据请求码和参数完成对设备的控制操作。 - 设备驱动程序将处理结果返回给内核空间。 - 内核空间将处理结果返回给用户空间,并返回给用户程序。 需要注意的是,具体的ioctl实现可能因操作系统和设备驱动的不同而有所差异。但是,整体的原理都是基于用户空间和内核空间之间的交互来完成设备操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值