SylixOS字符设备驱动开发(九)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月17日22:57:17 3 1,658

SylixOS设备操作之read和write

有些设备可能会和应用层有大量的数据进行传输,比如网卡、硬盘等等,这时候用ioctl来和应用层传输数据就显得不怎么适合了,因为ioctl一般是用来进行对设备进行控制的,而不是大量数据传输,传输大量数据就需要用到read和write接口。

驱动层的read接口函数原型:

ssize_t demo_read(demo_dev_t *dev, char *buf, size_t size);

buf 是应用层buffer地址,用来存放从驱动中读取到的数据,size 表示应用层希望读取的数据大小。函数失败返回PX_ERROR,正常返回读取成功的数据大小,如果没有数据可读,返回0。

如果可读数据大小比用户需要读取的大,则函数返回用户需要读取的大小。

我们设计demo_read函数只是简单的复制一段字符串数据给应用层表示读取数据:

static ssize_t demo_read(demo_dev_t *dev, char *buf, size_t size)
{
#define DRIVER_READ_DATA "<data from demo driver>"
    char *rdata = DRIVER_READ_DATA;
    int rdata_len = strlen(DRIVER_READ_DATA);

    printk("%s.\r\n", __func__);

    rdata_len = (size > rdata_len) ? rdata_len : size;
    memcpy(buf, rdata, rdata_len);

    return rdata_len;
}

类似的,驱动层的write接口函数原型:

ssize_t demo_write(demo_dev_t *dev, char *buf, size_t size);

buf 是应用层buffer地址,用来存放应用层要写的数据,size 表示应用层希望写入的数据大小。函数失败返回PX_ERROR,正常返回写入成功的数据大小,如果没有数据写入,返回0。

我们设计demo_write函数只是从应用层简单的复制一段字符串数据给驱动层表示写入数据:

static ssize_t demo_write(demo_dev_t *dev, char *buf, size_t size)
{
    char wdata[30] = {0};
    int wdata_len = 30;

    printk("%s.\r\n", __func__);

    wdata_len = (size < wdata_len) ? size : wdata_len;
    memcpy(wdata, buf, size);

    printk("write data %s success.\r\n", wdata);

    return wdata_len;
}

应用层首先需要定义分别用于读写的buffer:

char rbuffer[30]= {0};
char wbuffer[30] = "<data from app>";

写入的数据这里固定为一个字符串。读取数据的处理:

ret = read(fd, rbuffer, 30);
if (ret < 0) {
    printf("read data fail.\r\n");
    close(fd);
    return -1;
} else if (ret == 0) {
    printf("read data end.\r\n");
} else {
    printf("read %d data,data is: %s.\r\n", ret, rbuffer);
}

由于read和write的返回值表示实际读取或者写入的数据大小,这个值可能比你实际想要读取或者写入的大小要小,所以一定要判断返回值,如果不满足的话可能需要发起多次read和write直到满足。

写入数据的处理:

ret = write(fd, wbuffer, strlen(wbuffer));
if (ret < 0) {
    printf("write data fail.\r\n");
    close(fd);
    return -1;
} else if (ret == 0) {
    printf("write data end.\r\n");
} else {
    printf("write %d data success.\r\n", ret);
}

app执行的结果:

[root@sylixos:/apps/app_demo9]# ./app_demo9
demo_open .
open read/write.
file permission: 644.
demo_read.
read 23 data,data is: <data from demo driver>.
demo_write.
write data <data from app> success.
write 15 data success.
demo_close.
[root@sylixos:/apps/app_demo9]#

附源码

driver_demo9源码:

#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>
#include <string.h>
#include "driver.h"

typedef struct _demo_dev {
    LW_DEV_HDR dev;
    void *priv;
} demo_dev_t;

int drv_index;
demo_dev_t demo_dev[2];

static long demo_open(LW_DEV_HDR *dev, char *name, int flag, int mode)
{
    demo_dev_t *device = (demo_dev_t *)dev;
    device->priv = NULL;

    printk("%s %s.\r\n", __func__, name);

    if ((flag & O_ACCMODE) == O_RDONLY) {
        printk("open read only.\r\n");
    } else if ((flag & O_ACCMODE) == O_WRONLY) {
        printk("open write only.\r\n");
    } else {
        printk("open read/write.\r\n");
    }

    printk("file permission: %o.\r\n", mode);

    LW_DEV_INC_USE_COUNT(&device->dev);

    return (long)device;
}

static int demo_close(demo_dev_t *dev)
{
    printk("%s.\r\n", __func__);

    LW_DEV_DEC_USE_COUNT(&dev->dev);

    return ERROR_NONE;
}

static int demo_ioctl(demo_dev_t *dev, int cmd, long arg)
{
    struct stat *pstat;
    struct data *data;

    printk("%s %x.\r\n", __func__, cmd);

    switch (cmd) {
    case FIOFSTATGET:
        pstat = (struct stat *)arg;
        if (!pstat) {
            return  (PX_ERROR);
        }

        pstat->st_dev     = LW_DEV_MAKE_STDEV(&dev->dev);
        pstat->st_ino     = (ino_t)0;
        pstat->st_mode    = (S_IRWXU | S_IRWXG | S_IRWXO | S_IFCHR);
        pstat->st_nlink   = 1;
        pstat->st_uid     = 0;
        pstat->st_gid     = 0;
        pstat->st_rdev    = 0;
        pstat->st_size    = 0;
        pstat->st_blksize = 0;
        pstat->st_blocks  = 0;
        pstat->st_atime   = API_RootFsTime(LW_NULL);
        pstat->st_mtime   = API_RootFsTime(LW_NULL);
        pstat->st_ctime   = API_RootFsTime(LW_NULL);
        break;

    case CMD_GET_VERSION:
        data = (struct data *)arg;
        data->version = 3;
        break;

    default:
        return  (PX_ERROR);
    }

    return ERROR_NONE;
}

static ssize_t demo_read(demo_dev_t *dev, char *buf, size_t size)
{
#define DRIVER_READ_DATA "<data from demo driver>"
    char *rdata = DRIVER_READ_DATA;
    int rdata_len = strlen(DRIVER_READ_DATA);

    printk("%s.\r\n", __func__);

    rdata_len = (size > rdata_len) ? rdata_len : size;
    memcpy(buf, rdata, rdata_len);

    return rdata_len;
}

static ssize_t demo_write(demo_dev_t *dev, char *buf, size_t size)
{
    char wdata[30] = {0};
    int wdata_len = 30;

    printk("%s.\r\n", __func__);

    wdata_len = (size < wdata_len) ? size : wdata_len;
    memcpy(wdata, buf, size);

    printk("write data %s success.\r\n", wdata);

    return wdata_len;
}

static struct file_operations demo_fops = {
    .owner    = THIS_MODULE,
    .fo_open  = demo_open,
    .fo_close = demo_close,
    .fo_ioctl = demo_ioctl,
    .fo_read  = demo_read,
    .fo_write = demo_write,
};

int module_init (void)
{
    int ret = 0;

    drv_index = iosDrvInstallEx(&demo_fops);
    if (drv_index < 0) {
        printk("driver install fail.\r\n");
        return -1;
    }

    DRIVER_LICENSE(drv_index, "GPL->Ver 2.0");
    DRIVER_AUTHOR(drv_index, "GeWenBin");
    DRIVER_DESCRIPTION(drv_index, "demo driver.");

    ret = iosDevAdd(&demo_dev[0].dev, "/dev/demo0", drv_index);
    if (ret != ERROR_NONE) {
        printk("device add fail.\r\n");
        iosDrvRemove(drv_index, TRUE);
        return -1;
    }

    ret = iosDevAdd(&demo_dev[1].dev, "/dev/demo1", drv_index);
    if (ret != ERROR_NONE) {
        printk("device1 add fail.\r\n");
        iosDevDelete(&demo_dev[0].dev);
        iosDrvRemove(drv_index, TRUE);
        return -1;
    }

    return 0;
}

void module_exit (void)
{
    iosDevDelete(&demo_dev[0].dev);
    iosDevDelete(&demo_dev[1].dev);
    iosDrvRemove(drv_index, TRUE);
}

app_demo9源码:

#include <stdio.h>
#include <string.h>

int main (int argc, char **argv)
{
    int fd;
    int ret = 0;
    char rbuffer[30]= {0};
    char wbuffer[30] = "<data from app>";

    fd =  open("/dev/demo0", O_RDWR);
    if (fd < 0) {
        printf("open file fail.\r\n");
        return -1;
    }

    ret = read(fd, rbuffer, 30);
    if (ret < 0) {
        printf("read data fail.\r\n");
        close(fd);
        return -1;
    } else if (ret == 0) {
        printf("read data end.\r\n");
    } else {
        printf("read %d data,data is: %s.\r\n", ret, rbuffer);
    }

    ret = write(fd, wbuffer, strlen(wbuffer));
    if (ret < 0) {
        printf("write data fail.\r\n");
        close(fd);
        return -1;
    } else if (ret == 0) {
        printf("write data end.\r\n");
    } else {
        printf("write %d data success.\r\n", ret);
    }

    close(fd);

    return  (0);
}

 

gewenbin
  • 本文由 发表于 2020年12月17日22:57:17
  • 转载请务必保留本文链接:http://www.databusworld.cn/8949.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

评论:3   其中:访客  3   博主  0
    • liqingquan liqingquan 3

      看完。

      • liqingquan liqingquan 3

        打卡!

        • zhanghang3252 zhanghang3252 0

          悟了