Advanced IO Operations – Positioning Operations

Hits: 0

positioning operation

Driver code:

/* vfb.c */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

#define VFB_MAJOR   256
#define VFB_MINOR   1
#define VFB_DEV_CNT 1
#define VFB_DEV_NAME    "vfbdev"

struct vfb_dev {
    unsigned char *buf;
    struct cdev cdev;
};

static struct vfb_dev vfbdev;

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

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

static int vfb_mmap(struct file *filp, struct vm_area_struct *vma)
{
    if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(vfbdev.buf) >> PAGE_SHIFT, \
        vma->vm_end - vma->vm_start, vma->vm_page_prot))
        return -EAGAIN;
    return 0;
}

ssize_t vfb_read(struct file *filp, char __user *buf, size_t count, loff_t *pos)
{
    int ret;
     size_t len ​​= (count > PAGE_SIZE) ? PAGE_SIZE : count;
     //Determine whether the file access exceeds the boundary 
    //Exceeds the length of the adjustment access 
    if (*pos + len > PAGE_SIZE)
        len = PAGE_SIZE - *pos;

    ret = copy_to_user(buf, vfbdev.buf + *pos, len);
    *pos += len - right;

    return len - ret;
}
//File positioning operation 
static loff_t vfb_llseek (struct file * filp, loff_t off, int whence)
 {
     loff_t newpos;

    switch (whence) {
    case SEEK_SET:
        newpos = off;
        break;
    case SEEK_CUR:
        newpos = filp->f_pos + off;
        break;
    case SEEK_END:
        newpos = PAGE_SIZE + off;
        break;
    default:                /* can't happen */
        return -EINVAL;
    }
    //Determine whether the new position value is legal 
    if (newpos < 0 || newpos > PAGE_SIZE)
         return -EINVAL;
     //Update the new file position value to the f_pos member of the file structure
    filp->f_pos = newpos;

    return newpos;
}

static struct file_operations vfb_fops = {
    .owner = THIS_MODULE,
    .open = vfb_open,
    .release = vfb_release,
    .mmap = vfb_mmap,
    .read = vfb_read,
    .llseek = vfb_llseek,
};

static int __init vfb_init(void)
{
    int ret;
    dev_t dev;
    unsigned long addr;

    dev = MKDEV(VFB_MAJOR, VFB_MINOR);
    ret = register_chrdev_region(dev, VFB_DEV_CNT, VFB_DEV_NAME);
    if (ret)
        goto reg_err;

    cdev_init(&vfbdev.cdev, &vfb_fops);
    vfbdev.cdev.owner = THIS_MODULE;
    ret = cdev_add(&vfbdev.cdev, dev, VFB_DEV_CNT);
    if (ret)
        goto add_err;

    addr = __get_free_page(GFP_KERNEL);
    if (!addr)
        goto get_err;

    vfbdev.buf = (unsigned char *)addr;
    memset(vfbdev.buf, 0, PAGE_SIZE);

    return 0;

get_err:
    cdev_del(&vfbdev.cdev);
add_err:
    unregister_chrdev_region(dev, VFB_DEV_CNT);
reg_err:
    return ret;
}

static void __exit vfb_exit(void)
{
    dev_t dev;

    dev = MKDEV(VFB_MAJOR, VFB_MINOR);

    free_page((unsigned long)vfbdev.buf);
    cdev_del(&vfbdev.cdev);
    unregister_chrdev_region(dev, VFB_DEV_CNT);
}

module_init(vfb_init);
module_exit(vfb_exit);

MODULE_LICENSE("GPL");

Lines 45 and 46 of the driver code determine whether the file access exceeds the boundary, and if so, adjust the length of the access.

Code line 48 takes into account the effect of offset when copying

Line 49 of the code is to update the position value.

Lines 54 to 78 of the code [are] the implementation of the file positioning operation. Depending on whence, a new file position value is set

Lines 72 and 73 of the code are to determine whether the new position value is legal

Code line 75 updates the new file position value to the f_pos member of the file structure

Test program code:

/* test.c */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>

int main(int argc, char * argv[])
{
    int fd;
    char *start;
    int i;
    char buf[32];

    fd = open("/dev/vfb0", O_RDWR);
    if (fd == -1)
        goto fail;

    start = mmap(NULL, 32, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (start == MAP_FAILED)
        goto fail;

    for (i = 0; i < 26; i++)
        *(start + i) = 'a' + i;
    *(start + i) = '
/* test.c */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
int main(int argc, char * argv[])
{
int fd;
char *start;
int i;
char buf[32];
fd = open("/dev/vfb0", O_RDWR);
if (fd == -1)
goto fail;
start = mmap(NULL, 32, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (start == MAP_FAILED)
goto fail;
for (i = 0; i < 26; i++)
*(start + i) = 'a' + i;
*(start + i) = '\0';
if(lseek(fd, 3, SEEK_SET) == -1)
goto fail;
if (read(fd, buf, 10) == -1)
goto fail;
buf[10] = '\0';
puts(buf);
munmap(start, 32);
return 0;
fail:
perror("mmap test");
exit(EXIT_FAILURE);
}
'; if(lseek(fd, 3, SEEK_SET) == -1) goto fail; if (read(fd, buf, 10) == -1) goto fail; buf[10] = '
/* test.c */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
int main(int argc, char * argv[])
{
int fd;
char *start;
int i;
char buf[32];
fd = open("/dev/vfb0", O_RDWR);
if (fd == -1)
goto fail;
start = mmap(NULL, 32, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (start == MAP_FAILED)
goto fail;
for (i = 0; i < 26; i++)
*(start + i) = 'a' + i;
*(start + i) = '\0';
if(lseek(fd, 3, SEEK_SET) == -1)
goto fail;
if (read(fd, buf, 10) == -1)
goto fail;
buf[10] = '\0';
puts(buf);
munmap(start, 32);
return 0;
fail:
perror("mmap test");
exit(EXIT_FAILURE);
}
'; puts(buf); munmap(start, 32); return 0; fail: perror("mmap test"); exit(EXIT_FAILURE); }

The change of the test program compared to the previous article is that the file position is first positioned as 3 using lseek before the read operation, and then the subsequent operations are read from the third byte of the file.

if(lseek(fd, 3, SEEK_SET) == -1)
        goto fail;

if (read(fd, buf, 10) == -1)
        goto fail;

The compilation result is as follows:

abcd corresponds to the file location (array) 0 1 2 3

Because it is read from the 3rd byte, i.e. d

read 10

read(fd, buf, 10)、

Read 10 bytes from buf buffer

defghijklm 10

So far the I/O operation is over

You may also like...

Leave a Reply

Your email address will not be published.