c - IOCTL 调用不适用于驱动程序

标签 c linux-kernel linux-device-driver device-driver ioctl

我编写了一个 IOCTL 驱动程序和一个相应的 ioctl 应用程序,其中包含一个包含命令的头文件。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include "myioctl.h"
#include <linux/ioctl.h>



#define NAME MyCharDevice


//Function Prototypes
int NAME_open(struct inode *inode, struct file *filp);
int NAME_release(struct inode *indoe, struct file *filp);
ssize_t NAME_write(struct file *filp, char __user *Ubuff, size_t count, loff_t  *offp);
ssize_t NAME_read(struct file *filp, char __user *Ubuff, size_t count, loff_t  *offp);
int NAME_flush (struct file *filp);
int NAME_IOCTL (struct inode *inode, struct file *filp, unsigned long cmd, unsigned long val);



//Structure that defines the operations that the driver provides
struct file_operations fops = 
{
    .owner   = THIS_MODULE,
    .open    = NAME_open, 
    .read    = NAME_read,
    .write   = NAME_write,
    .unlocked_ioctl  = NAME_IOCTL,
    .release = NAME_release,
    .flush   = NAME_flush,
};

//Structure for a character driver
struct cdev *my_cdev;


//Init Module
static int __init CharDevice_init(void)
{
    int result;
    int MAJOR,MINOR;
    dev_t Mydev;
    Mydev = MKDEV(255,0);//Create a device number
    MAJOR=MAJOR(Mydev);
    MINOR=MINOR(Mydev);
    printk("\nThe Major Number is %d...THe Minor Number is %d\n",MAJOR,MINOR);
    result=register_chrdev_region(Mydev,1,"MyCharDevice");//register device region.....
    if(result<0)
    {
        printk(KERN_ALERT "\nThe Region requested for is not obtainable\n");
        return(-1);
    }

    my_cdev = cdev_alloc();//allocate memory to Char Device structure
    my_cdev->ops = &fops;//link our file operations to the char device

    result=cdev_add(my_cdev,Mydev,1);//Notify the kernel abt the new device
    if(result<0)
    {
        printk(KERN_ALERT "\nThe Char Devide has not been created......\n");
        return (-1);
    }
    return 0;
}


//Cleanup Module
void __exit CharDevice_exit(void)
{
    dev_t Mydev;
    int MAJOR,MINOR;
    Mydev=MKDEV(255,0);
    MAJOR=MAJOR(Mydev);
    MINOR=MINOR(Mydev);
    printk("\nThe Major Number is %d...THe Minor Number is %d\n",MAJOR,MINOR);
    unregister_chrdev_region(Mydev,1);//unregister the device numbers and the device created
    cdev_del(my_cdev);
    printk(KERN_ALERT "\nI have unregistered the stuff that was allocated.....Goodbye for ever.....\n");
    return;
}

int NAME_IOCTL (struct inode *inode, struct file *filp, unsigned long cmd, unsigned long val)
{
    int BAUD=0, STOP;
    char PARITY, CONFIG;
printk ("In IOCTL\n");
printk("command = %d %d val = %d\n", cmd, SET_BAUD, val);
    switch (cmd) {

        case SET_BAUD:
            get_user (BAUD, (int *)val);    
            printk ("The baud is %d", BAUD);

        case SET_PARITY:


        case SET_STOP:


        case READ_CONFIG:


        default:
            return -1;
    }
    return 0;   
}

//Open System Call
int NAME_open(struct inode *inode, struct file *filp)
{
    printk(KERN_ALERT "\nThis is the Kernel....Open Call.....I have nothing to do.....but YOU ALL HAVE....HAHAHAHA...\n");
    return 0;
}

//Close System Call
int NAME_release(struct inode *indoe, struct file *filp)
{
    printk(KERN_ALERT "\nThis is the release method of my Character Driver......Bye Dudes......\n");
    return 0;
} 


//Write Functionality
ssize_t NAME_write(struct file *filp, char __user *Ubuff, size_t count, loff_t  *offp)
{
    char Kbuff[80];
    unsigned long result;
    ssize_t retval;
    //strcpy(Kbuff,Ubuff);
    result=copy_from_user((char *)Kbuff,(char *)Ubuff,count); //get user data
    if(result==0)
    {
        printk(KERN_ALERT "\nMessage from the user......\n>>>> %s <<<<\n",Kbuff);
        printk(KERN_ALERT "\n Data Successfully Written.....\n");   
        retval=count;
        return retval;
    }
    else
    {
        printk(KERN_ALERT "\n Error Writing Data\n");
        retval=-EFAULT;
        return retval;
    }
}

//read Functionality    
ssize_t NAME_read(struct file *filp, char __user *Ubuff, size_t count, loff_t  *offp)
{
    char Kbuff[]="THis is some date from the kernel to the user....User,ENJOY......";
    unsigned long result;
    ssize_t retval;
    //strcpy(Kbuff,Ubuff);
    result=copy_to_user((char *)Ubuff,(char *)Kbuff,sizeof(Kbuff)); //copy to user
    if(result==0)
    {
        //printk("\nMessage from the user......\n>>>> %s <<<<\n");
        printk(KERN_ALERT "\n Data Successfully read.....\n");  
        retval=count;
        return retval;
    }
    else
    {
        printk(KERN_ALERT"\n Error Writing Data to User\n");
        retval=-EFAULT;
        return retval;
    }
}   

int NAME_flush (struct file *filp)
{
    printk("\n This is the close function of the file....");
    return 0;
}

//Module over ride functions
module_init(CharDevice_init);
module_exit(CharDevice_exit);

头文件

#define MAGIC 'x'

#define SET_BAUD _IOW(MAGIC,0, int)
#define SET_PARITY _IOW(MAGIC, 1, char)
#define SET_STOP _IOW(MAGIC, 2, int)
#define READ_CONFIG _IOR(MAGIC, 3, int)

c文件

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#include "myioctl.h"
int main()
{
    int FileDesc, Baud=9600;
//  char Ubuff[]="THis is the User Buffer......Sending Data to the Kernel....";
//  char Kbuff[100];    
    FileDesc=open("/dev/MyCharDevice",O_RDWR);
    if(FileDesc <0)
    {
        printf("\nError Opening Device\n"); 
        exit(1);
    }
    ioctl (FileDesc, SET_BAUD, &Baud);
    printf("%d %d \n", SET_BAUD, &Baud);

//  write(FileDesc,Ubuff,sizeof(Ubuff));
//  read(FileDesc,Kbuff,sizeof(Ubuff));
//  printf("\n The Data read from the Kernel is\n>>>> %s <<<<\n",Kbuff);
    close(FileDesc);
}

我在驱动程序中打印像这样打印的命令和参数值是什么

command = 1622004312 1074034688 val = 1622004312

所以发送的命令等于我发送的参数。为什么会发生这种情况?

最佳答案

我在驱动程序中使用了较旧的 IOCTL 原型(prototype)。 应该是这种类型

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
static int my_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
#else
static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
#endif

就我的内核而言

static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)

是正确的类型。

关于c - IOCTL 调用不适用于驱动程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42488086/

相关文章:

c - 有人为 MSP430 的 IAR Embedded Workbench 实现了 __getzone() 吗?

c - rand 应该用于 IV 吗?

linux-kernel - 从内核空间访问 GPIO

linux - 网络驱动程序轮询中断中的致命异常

linux - 调用 netlink_broadcast() 导致 BUG 调度而 atomic

c - 来自命令行参数的输入有效,但来自内部 char* 的输入给出总线错误。不应该是一样的吗?

c - 在 C 中格式化日期

sockets - 在Linux内核中发送UDP数据包

c - 为什么 Linux 内核模块符号不能正确地全局导出?

linux - 在 ARM 的其他 cpu 内核中运行内核函数