linux驱动实现ioctl传递结构体

通常用户空间和内核空间的交互利用read和write即可实现,部分特殊情况下可利用ioctl更加便捷。以下为驱动添加ioctl函数定义,处理用户空间传递来的各种指令并交互结构体。(其中函数第三个参数arg默认为unsigned long类型四字节,但大部分情况传递的都是地址,该四字节存的本身就是地址,因此使用copy***user函数的时候无需对其加&取地址符)

结合上一篇linux驱动开发简单示例,在zhancghen_test.c中添加如下代码:

//新增传输的数据结构体
typedef struct
{
    int iNum;
    char aData[128];
}tTransferBuf;
//新增魔术和指令宏定义
#define ZHANGCHEN_TEST_MAGIC         'a'
#define ZHANGCHEN_TEST_CMD_SET_VAL   _IOW(ZHANGCHEN_TEST_MAGIC, 1, tTransferBuf)
#define ZHANGCHEN_TEST_CMD_GET_VAL   _IOR(ZHANGCHEN_TEST_MAGIC, 2, tTransferBuf)
static tTransferBuf g_s_buffer;

//增加ioctl函数映射
static struct file_operations g_test_fops = {
    ...
    ...
    .unlocked_ioctl = zhangchen_test_ioctl,
};

//驱动内ioctl定义,利用switch处理各种指令
static long zhangchen_test_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
    int ret = 0;

    if (_IOC_TYPE(cmd) != ZHANGCHEN_TEST_MAGIC) {
        pr_err("%s: command type [%c] error.\n", __func__, _IOC_TYPE(cmd));
        return -ENOTTY;
    }

    switch(cmd) {
        case ZHANGCHEN_TEST_CMD_SET_VAL:
            printk("Transfer arg[%lu]\n" , arg);
            if(copy_from_user(&g_s_buffer , (tTransferBuf *)arg , sizeof(tTransferBuf)))
            {
                printk(KERN_ALERT "Func copy_from_user failed!\n");
                return -EFAULT;
            }
            printk("Func ioctl set id[%d] data[%s]\n" , g_s_buffer.iNum , g_s_buffer.aData);
            ret = 1;
            break;
        case ZHANGCHEN_TEST_CMD_GET_VAL:
            if(copy_to_user((tTransferBuf *)arg , &g_s_buffer , sizeof(tTransferBuf)))
            {
                printk(KERN_ALERT "Func copy_to_user failed!\n");
                return -EFAULT;
            }
            printk("Func ioctl get id[%d] data[%s]\n" , g_s_buffer.iNum , g_s_buffer.aData);
            ret = 2;
            break;
        default:
            pr_err("%s: invalid command.\n", __func__);
            ret = -ENOTTY;
            break;
    }

    return ret;
}

测试代码test.c:

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

typedef struct
{
    int iNum;
    char aData[128];
}tTransferBuf;
#define ZHANGCHEN_TEST_MAGIC         'a'
#define ZHANGCHEN_TEST_CMD_SET_VAL   _IOW(ZHANGCHEN_TEST_MAGIC, 1, tTransferBuf)
#define ZHANGCHEN_TEST_CMD_GET_VAL   _IOR(ZHANGCHEN_TEST_MAGIC, 2, tTransferBuf)

int main(int argc,char **argv)
{
    int fd;
    tTransferBuf stTmp;

    fd = open("/dev/zhangchen_dev",O_RDWR);
    if(-1==fd)
    {
        printf("Func open failed!\n");
        return -1;
    }
    
    memset(&stTmp , 0 , sizeof(stTmp));
    stTmp.iNum = 666;
    strcpy(stTmp.aData , "zzzz");
    if(ioctl(fd , ZHANGCHEN_TEST_CMD_SET_VAL , &stTmp) < 0)
    {
        printf("Func ioctl failed!\n");
        return -2;
    }
    printf("Ioctl set id[%d] data[%s]\n" , stTmp.iNum , stTmp.aData);


    memset(&stTmp , 0 , sizeof(stTmp));
    if(ioctl(fd , ZHANGCHEN_TEST_CMD_GET_VAL, &stTmp) < 0)
    {
        printf("Func ioctl failed!\n");
        return -2;
    }
    printf("Ioctl get id[%d] data[%s]\n" , stTmp.iNum , stTmp.aData);


    close(fd);

    puts("Exit");

    return  0;
}

猜你喜欢

转载自blog.csdn.net/jiujiederoushan/article/details/128948762
今日推荐