OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3488|回复: 2

求助驱动开发中,ioctl的问题

[复制链接]

1

主题

3

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2020-11-27
在线时间
10 小时
发表于 2022-5-10 09:23:23 | 显示全部楼层 |阅读模式
3金钱
先看代码:

1、驱动程序:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>

#define TIMER_DEV_NAME  "test"
#define TIMER_DEV_COUNT 1

#define CMD_RUN     (_IO('T', 0x54))
#define CMD_STOP    (_IO('T', 0x53))

struct timer_dev_type {
    dev_t dev_id;
    struct cdev cdev;
    struct class *class;
    struct device *device;
    int major;
};
struct timer_dev_type timer_dev;

static int timer_dev_open(struct inode *inode, struct file *file)
{
    return 0;
}

long timer_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{   
    switch(cmd)
    {
        case CMD_RUN:
            printk("Running!\n");
            break;
        case CMD_STOP:
            printk("Stopped!\n");
            break;
    }

    return 0;
}

static struct file_operations timer_dev_ops = {
    .owner = THIS_MODULE,
    .open = timer_dev_open,
    .unlocked_ioctl = timer_dev_ioctl,
};

static int __init timer_dev_init(void)
{
    int err = 0;

    /* 1、创建设备号 */
    if(timer_dev.major)
    {
        timer_dev.dev_id = MKDEV(timer_dev.major, 0);
        register_chrdev_region(timer_dev.dev_id, TIMER_DEV_COUNT, TIMER_DEV_NAME);
    }
    else
    {
        alloc_chrdev_region(&timer_dev.dev_id, 0, TIMER_DEV_COUNT, TIMER_DEV_NAME);
        timer_dev.major = MAJOR(timer_dev.dev_id);
    }

    /* 2、初始并添加字符设备 */
    timer_dev.cdev.owner = THIS_MODULE;
    cdev_init(&timer_dev.cdev, &timer_dev_ops);
    cdev_add(&timer_dev.cdev, timer_dev.dev_id, TIMER_DEV_COUNT);

    /* 3、创建类 */
    timer_dev.class = class_create(THIS_MODULE, TIMER_DEV_NAME);
    if(IS_ERR(timer_dev.class))
    {
        printk("Error: Failed to create timer class!\n");
        return -EINVAL;
    }

    /* 4、创建设备 */
    timer_dev.device = device_create(timer_dev.class, NULL, timer_dev.dev_id, NULL, TIMER_DEV_NAME);
    if(IS_ERR(timer_dev.device))
    {
        printk("Error: Failed to create device!\n");
        return -EINVAL;
    }

    return err;
}

static void __exit timer_dev_exit(void)
{
    /* 1、删除设备 */
    device_destroy(timer_dev.class, timer_dev.dev_id);
    /* 2、删除类 */
    class_destroy(timer_dev.class);
    /* 3、注销字符设备 */
    cdev_del(&timer_dev.cdev);
    /* 4、释放设备号 */
    unregister_chrdev_region(timer_dev.dev_id, TIMER_DEV_COUNT);
}

module_init(timer_dev_init);
module_exit(timer_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LSW");




2、应用程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define CMD_RUN     (_IO('T', 0x54))
#define CMD_STOP    (_IO('T', 0x53))

int main(int argc, char const *argv[])
{
    int err = 0;
    int fd;
    const char *filename = argv[1];
    unsigned char cmd;

    /* 打开文件 */
    fd = open(filename, O_RDWR);
    if(fd < 0)
    {
        printf("Error: Could not open file: %s\n", filename);
        return -1;
    }

#if 0   /* 代码1:直接调用ioctl */
    /* 能成功实现 */
    ioctl(fd, CMD_RUN);
    ioctl(fd, CMD_STOP);

#else   /* 代码2:通过键盘输入命令,再通过命令调用ioctl */
    /* 不能实现 */
    printf("Please input cmd:");
    err = scanf("%d", &cmd);
    if(err != 1)        // 防止卡死
    {
        while(getchar() != '\n');
    }

    if(cmd == 1)
    {
        err = ioctl(fd, CMD_RUN);
        if(err != 0)
        {
            printf("ioctl error: %d\n", err);
        }
        printf("cmd1 executed!\n");
    }
    else if(cmd == 2)
    {
        err = ioctl(fd, CMD_STOP);
        if(err != 0)
        {
            printf("ioctl error: %d\n", err);
        }
        printf("cmd2 executed!\n");
    }   
#endif

    /* 关闭文件 */
    err = close(fd);
    if(err < 0)
    {
        printf("Error: Could not close file: %s\n");
        return -1;
    }

    return 0;
}






问题描述

    在应用程序中,如果直接调用ioctl函数(代码1)时,驱动程序中的ioctl能成功打印,

但是,如果应用程序中,用代码2来调用时,虽然没有报错,但是就是没有代用到驱动程序的ioctl

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

80

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1028
金钱
1028
注册时间
2019-1-5
在线时间
243 小时
发表于 2022-5-13 10:00:30 | 显示全部楼层
意思是代码2没有调用进入ioctl?  
如果没有打印 printf("cmd1 executed!\n");或者 printf("cmd2 executed!\n");
你打印一下键盘输入的变量cmd看看,,,
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2020-11-27
在线时间
10 小时
 楼主| 发表于 2022-5-15 11:49:04 | 显示全部楼层
s2333 发表于 2022-5-13 10:00
意思是代码2没有调用进入ioctl?  
如果没有打印 printf("cmd1 executed!\n");或者 printf("cmd2 executed! ...

对的,代码2没有调用到驱动文件的ioctl
后面发现,是调用scanf后,把文件描述符fd改为0了,
但是,又不清楚scanf为什么会修改到fd
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 10:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表