了解文件操作的 loff_t *offp [英] Understanding loff_t *offp for file_operations

查看:16
本文介绍了了解文件操作的 loff_t *offp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一个简单的读取和写入字符缓冲区的设备驱动程序.然而,我的问题是关于file_operations 结构readwrite 中的两个函数.我真的不明白 loff_t *offp 到底是什么.我知道对于读取和写入操作, *offp 是文件偏移量,表示文件的当前读取/写入位置,但是我什至不确定写入或读取意味着什么/来自设备文件.

从我收集到的,这就是我从我的设备写入和读取的方式,我创建了一个代表我的设备的结构,我称之为 my_char_struct,如下所示.

struct my_char_structure{结构 cdev my_cdev;结构信号量 sem;字符*数据;ssize_t 数据大小;无符号 int access_key;无符号长尺寸;};

这是一个静态结构,当我的驱动程序是 insmod 时初始化并指向它.

static dev_t dev_num;静态结构 my_char_structure Dev;int start_mod(void){//因为我们正在处理一个虚构的设备,我想要//任意创建我的两个设备的驱动程序//分配的主要编号.struct my_char_structure *my_dev = &Dev;错误;alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME);sema_init(&(my_dev->sem),1);cdev_init(&(my_dev->my_cdev), &fops);my_dev->my_cdev.owner = THIS_MODULE;my_dev->my_cdev.ops = &fops;//fops 是我的文件操作结构err = cdev_add(&my_dev->my_cdev, dev_num, COUNT);如果(错误<0)printk(KERN_ALERT "出现错误 %d.",err);printk(KERN_ALERT " insmod to Major number %d",MAJOR(dev_num));返回0;}模块初始化(start_mod);

当我的设备打开时,我只是为打开的文件创建一个指针,指向我在 module_init(start_mod) 期间设置的那个静态结构......

int dev_open(struct inode *in_node, struct file *filp){静态结构 my_char_structure *my_dev;my_dev = container_of(in_node->i_cdev, struct my_char_structure, my_cdev);printk(KERN_ALERT "设备号为 %d",iminor(in_node));如果(!my_dev)printk(KERN_ALERT "有些东西没有用.my_dev 没有初始化.");filp->private_data = my_dev;返回0;}

我的读写方法所做的是修改我在打开的文件中指向的初始结构 Dev.无论我 copy_to_user 从我的结构中如何,都是用户认为已写入设备的内容,以及用户认为他们正在编写的内容.但是除了改变我的初始结构 Dev 之外,文件位置或偏移的想法没有意义,除非它指的是指向内核中某些任意结构或类型的缓冲内存的指针.那是我对文件偏移量的唯一解释......这是正确的吗?这就是这里的 loff_t *offp 所指的吗?

write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)读取(结构文件 *filp,字符 __user *buff,size_t 计数,loff_t *offp)

(鉴于我的理解是正确的)当调用某些文件操作(例如读/写)而我没有亲自设置 *offp 时,loff_t *offp 最初设置为什么?

如果在最后一个file_operation offp = some_arbitrary_address(因为我是这么说的),那么当再次调用这个操作时offp会被设置成什么?

如果我有其他 file_opens 操作正在运行会发生什么,它会设置为最后一个 file_operation 留下的内容,还是会保留它使用的 file_open 操作的选项卡并将 *offp 替换为 file_open 的内容?

字符设备的概念对我来说太抽象了,因为它似乎设备本身甚至不像文件那样存储信息,而是保存信息的驱动程序.我希望我已经解释了我的迷茫,我会澄清任何我似乎模棱两可的事情.

解决方案

"loff_t" 是一个长偏移量",即统一了off_t的疯狂多样性的一个seek位置off64_t,等等,这样司机就可以直接使用loff_t,不用担心.

指针本身,在您进入驱动程序时,指向用户提供的偏移量(假设它是用户代码执行驱动程序访问——技术上内核可以提供自己的,但用户案例是想想)通过lseekllseeklseek64等,再通过普通的读写操作.考虑常规磁盘文件的情况:当您第一次打开文件时,您(作为用户)让内核提供一个数据结构来跟踪您在文件中的当前位置,这样,如果您 readwrite 一些字节,下一个 readwrite 从您离开的地方开始.

此外,如果您dup 文件描述符,或者在运行序列方面通过(例如)forkexec 执行等效操作在命令中,该搜索位置由所有继承进程共享.因此,在 shell 提示符下,命令:

(prog1; prog2; prog3) >输出文件

创建一个输出文件,然后dup将描述符复制到三个程序中,这样prog2写入的输出在输出后立即进入文件prog1,而 prog3 的输出跟在其他两个之后——这都是因为所有三个独立的进程共享相同的底层内核数据结构和相同的内部 loff_t.>

这同样适用于设备驱动程序文件.当你的读写函数被调用时,你会收到用户提供的当前偏移量",你可以(并且应该)根据需要更新它……假设有任何需要(例如,你想为用户提供常规文件的外观,包括在您读写时查找偏移量移动的事实).如果设备有一些寻道偏移的逻辑应用,你可以在这里使用它.

当然,设备驱动程序还有很多,这就是为什么有关于这些东西的整本书章节 (q.v.).:-)

I'm designing a device driver that simply reads and writes to a character buffer. My question is however regarding the two functions in the file_operations structure read and write. I don't truly understand what loff_t *offp really is. I know that for both the read and write operations that *offp is the file offset meaning the current reading/writing position of the file, however I'm not even sure what it means to write or read to/from a device file.

From what I gathered, and this is how I am writing and reading from my device is that I create a structure which represents my device which I call my_char_struct which is shown bellow.

struct my_char_structure{
    struct cdev my_cdev;
    struct semaphore sem;
    char *data;
    ssize_t data_size;
    unsigned int access_key;
    unsigned long size;
};

This is a static structure that is initialized and pointed to when my driver is insmod as such.

static dev_t dev_num;
static struct my_char_structure Dev;

int start_mod(void){
    //Because we are dealing with a fictitious device, I want
    //the driver to create my two devices with arbitrarily 
    //assigned major numbers.
    struct my_char_structure *my_dev = &Dev;
    int err;

    alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME);

    sema_init(&(my_dev->sem),1);

    cdev_init(&(my_dev->my_cdev), &fops);
    my_dev->my_cdev.owner = THIS_MODULE;
    my_dev->my_cdev.ops = &fops;// fops is my file operations struct

    err = cdev_add(&my_dev->my_cdev, dev_num, COUNT);
    if(err<0)
        printk(KERN_ALERT "There was an error %d.",err);
    printk(KERN_ALERT " insmod to major number %d",MAJOR(dev_num));

    return 0;   
}

module_init(start_mod);

When my device is open, I just make a pointer for the file open to point to that static structure that I've set up during module_init(start_mod) as such ...

int dev_open(struct inode *in_node, struct file *filp){
    static struct my_char_structure *my_dev;
    my_dev = container_of(in_node->i_cdev, struct my_char_structure, my_cdev);
    printk(KERN_ALERT "The device number is %d",iminor(in_node));
    if(!my_dev)
        printk(KERN_ALERT "something didn't work. my_dev not initialized.");
    filp->private_data = my_dev;
    return 0;
}

What my read and write methods do is modify that initial structure Dev, that I've pointed to with my open files. Whatever I copy_to_user from my structure is what the user considers been written to the device and whatever I copy_from_user the user thinks they're writing. But beyond changing my initial structure Dev, the idea of file position or offset doesn't make sense unless it refers to a pointer to buffered memory within the kernel for some arbitrary structure or type. Thats the only interpretation that I have for the file offset ... is this correct? Is that what the loff_t *offp here refers to?

write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

(given my understanding is correct) When some file_operation such as read/write is called and I hadn't set *offp personally, what is loff_t *offp initially set to?

If in the last file_operation offp = some_arbitrary_address(because I told it so), is that what the offp would be set to when this operation is called again?

What happens if I have other file_opens operations running, will it set to what the last file_operation left it as, or will it keep a tab of which file_open operation it used and replace *offp to what the file_open had it at?

The concept of a char device is too abstract for me when it seems that the device itself doesn't even store the information like a file should, but rather its the driver that saves the information. I hope I've explained my fogginess and I'll clear up anything that I seem ambiguous about.

解决方案

"loff_t" is a "long offset", i.e., a seek position that unifies the crazy diversity of off_t, off64_t, and so on, so that drivers can just use loff_t and not worry about it.

The pointer itself, at the time you get into the driver, points to the offset provided by the user (assuming it's user code doing the driver access—technically the kernel can provide its own, but the user case is the one to think about) via lseek or llseek or lseek64, etc., and then by ordinary read and write operations. Consider the case of a regular on-disk file: when you first open the file, you (as a user) get the kernel to provide a data structure that keeps track of your current position in the file, so that if you read or write some bytes, the next read or write picks up from where you left off.

Furthermore, if you dup the file descriptor, or do the equivalent by (e.g.) fork and exec in terms of running a sequence of commands, that seek-position is shared by all the inheriting processes. Hence, at the shell prompt, the command:

(prog1; prog2; prog3) > outputfile

creates an output file, then dups the descriptor to the three programs, so that output that prog2 writes goes into the file immediately after the output from prog1, and output from prog3 follows the other two—all because all three separate processes share the same underlying kernel data structure with the same internal loff_t.

The same applies to device driver files. When your read and write functions are called, you receive the "current offset" as provided by the user, and you can (and should) update it as needed ... assuming there is any need (e.g., you want to provide users with the appearance of a regular file, including the fact that seek offsets move as you read and write). If the device has some logical application of the seek offset, you can use that here.

Of course, there's a lot more to device drivers, which is why there are entire book-chapters on this stuff (q.v.). :-)

这篇关于了解文件操作的 loff_t *offp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆