ioctl实现例程

本文档提供了一个关于Linux内核ioctl命令实现的详细步骤。首先介绍了ioctl_basic.h头文件,接着展示用户态程序user_basic_ioctl.c的内容。通过insmod加载ioctl模块后,dmesg显示初始化信息,并给出设备的主要号码。运行用户应用程序后,dmesg日志显示open、ioctl操作和close过程的信息。最后,使用rmmod卸载模块,系统日志记录了清理过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本例程中代码使用如下博客:http://tuxthink.blogspot.com/2011/01/creating-ioctl-command.html

1.ioctl_basic.h

/*************************************************************************
	> File Name: ioctl_basic.h
	> Author: 
	> Mail: 
	> Created Time: Wed 22 Apr 2015 10:25:01 PM CST
 ************************************************************************/

#ifndef _IOCTL_BASIC_H
#define _IOCTL_BASIC_H
#include <linux/ioctl.h>
#define IOC_MAGIC 'k'
#define IOCTL_HELLO _IO(IOC_MAGIC,0) 
#endif
2.ioctl_basic.c

/*************************************************************************
	> File Name: ioctl_basic.c
	> Author: 
	> Mail: 
	> Created Time: Wed 22 Apr 2015 10:29:15 PM CST
 ************************************************************************/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h> // required for various structures related to files liked fops. 
#include <linux/semaphore.h>
#include <linux/cdev.h> 
#include "ioctl_basic.h"
#include <linux/version.h>
#include <linux/device.h>
static int Major;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
#define UNLOCKED 1
#endif

int open(struct inode *inode, struct file *filp)
{
     
     printk(KERN_INFO "Inside open \n");
     return 0;

}

int release(struct inode *inode, struct file *filp) {
     printk (KERN_INFO "Inside close \n");
     return 0;

}

#ifdef UNLOCKED

long ioctl_funcs(struct file *filp,unsigned int cmd, unsigned long arg)
{
    
    int ret=0;

    switch(cmd) {

        case IOCTL_HELLO: 
         printk(KERN_INFO "Hello ioctl world");
         break;
         
    } 
     
    return ret;
     

}

struct file_operations fops = {
     open:   open,
     unlocked_ioctl: ioctl_funcs,
     release: release

};



#else

int ioctl_funcs(struct inode *inode, struct file *filp,
                                unsigned int cmd, unsigned long arg)
{
    
    int data=10,ret;

    switch(cmd) {

        case IOCTL_HELLO: 
         printk(KERN_INFO "Hello ioctl world");
         break;
         
    } 
     
    return ret;
     

}

struct file_operations fops = {
     open:   open,
     ioctl:  ioctl_funcs,
     release: release

};


#endif

struct cdev *kernel_cdev; 
static struct class *cl;

int char_arr_init (void) {
     int ret;
    dev_t dev_no,dev;
    struct device *dev_ret;

     kernel_cdev = cdev_alloc(); 
      kernel_cdev->ops = &fops;
     kernel_cdev->owner = THIS_MODULE;
     printk (" Inside init module\n");
      ret = alloc_chrdev_region( &dev_no , 0, 1,"char_arr_dev" );
    if (ret < 0) {
          printk("Major number allocation is failed\n");
          return ret; 
         
    }
     
        Major = MAJOR(dev_no);
        dev = MKDEV(Major,0);
     printk (" The major number for your device is %d\n", Major);
     ret = cdev_add( kernel_cdev,dev,1 );
     if(ret < 0 ) 
    {
         printk(KERN_INFO "Unable to allocate cdev");
         return ret;
         
    }

    if (IS_ERR(cl = class_create(THIS_MODULE, "char")))
    {
                cdev_del(kernel_cdev);
                unregister_chrdev_region(dev_no, 1);
                return PTR_ERR(cl);
            
    }
        if (IS_ERR(dev_ret = device_create(cl, NULL, dev_no, NULL, "query")))
    {
                class_destroy(cl);
                cdev_del(kernel_cdev);
                unregister_chrdev_region(dev_no, 1);
                return PTR_ERR(dev_ret);
            
    }

     return 0;

}

void char_arr_cleanup(void) {
     printk(KERN_INFO " Inside cleanup_module\n");
     cdev_del(kernel_cdev);
     unregister_chrdev_region(Major, 1);

}
MODULE_LICENSE("GPL"); 
module_init(char_arr_init);
module_exit(char_arr_cleanup);

3.Makefile

ifneq ($(KERNELRELEASE),) 
   obj-m := ioctl_basic.o
   else 

KERNELDIR ?= /lib/modules/$(shell uname -r)/build 

PWD := $(shell pwd)

default: 
	 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
endif

4.make 命令生成ioctl_basic.ko模块

5.用户态例程user_basic_ioctl.c

/*************************************************************************
	> File Name: user_basic_ioctl.c
	> Author: 
	> Mail: 
	> Created Time: Wed 22 Apr 2015 10:32:34 PM CST
 ************************************************************************/

#include <stdio.h>
#include <fcntl.h>
#include "ioctl_basic.h"  //ioctl header file

int main (int argc, char * argv[]  ) {
    int fd;
    fd = open("/dev/query", O_RDWR);

    if (fd == -1)
    {
        printf("Error in opening file \n");
        exit(-1);
                
    }
           
    ioctl(fd,IOCTL_HELLO);  //ioctl call 

    close(fd);
    return 0;
}

6.gcc user_basic_ioctl.c -o user_app生成用户态程序user_app

7.加载ioctl模块

sudo insmod ioctl_basic.ko

通过dmesg命令查看日志,可以看到如下:

[ 5256.438408]  Inside init module                                                                                                                                                                                              
[ 5256.438413]  The major number for your device is 248 

8.运行sudo ./user_app

通过dmesg可以看到如下日志:

[ 5332.507302] Inside open                                                                                                                                                                                                      
[ 5332.507312] Hello ioctl world                                                                                                                                                                                               
[ 5332.507318] Inside close
9.卸载ioctl模块

sudo rmmod ioctl_basic.ko

通过dmesg系统日志可以看到

[ 6567.708057]  Inside cleanup_module

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值