【问题标题】:IOCTL call not working with driverIOCTL 调用不适用于驱动程序
【发布时间】:2017-02-27 14:22:25
【问题描述】:

我编写了一个 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

所以发送的命令等于我发送的参数。为什么会这样?

【问题讨论】:

  • 在 C 语言中,编译时始终启用所有警告,然后修复这些警告。 (对于gcc,至少使用:-Wall -Wextra -pedantic 我也使用:-Wconversion -std=gnu99
  • .c 文件缺少以下语句:#include &lt;stdlib.h&gt; 用于函数:exit()。 driver.c 文件缺少语句:#include &lt;sys/ioctl.h&gt; 函数:ioctl() 和语句:#include &lt;unistd.h&gt; for the function: close()` 头文件缺少所需的“包含保护”语句
  • 在此语句中:printf("%d %d \n", SET_BAUD, &amp;Baud);第三个参数与格式字符串中的第二个格式规范不匹配。

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


【解决方案1】:

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

#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)

是正确的类型。

【讨论】:

    猜你喜欢
    • 2011-11-30
    • 2011-05-11
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    相关资源
    最近更新 更多