一尘不染

了解loff_t * offp的file_operations

linux

我正在设计一个仅读取和写入字符缓冲区的设备驱动程序。但是我的问题是关于file_operations结构read和中的两个功能write。我不真正了解真正的含义loff_t *offp。我知道对于读取和写入操作而言,这*offp都是文件偏移量,即文件的当前读取/写入位置,但是我什至不知道对设备文件进行读写是什么意思。

从我收集的数据来看,这就是我在设备上进行写入和读取的方式,是我创建了一个表示我所称设备的结构,该结构在my_char_struct下面显示。

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

这是一个静态结构,在我的驱动程序本身处于初始化状态时会被初始化并指向该结构insmod

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);

当我的设备打开时,我只是打开了一个指向文件的指针,以指向在此过程中设置的静态结构module_init(start_mod)

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;
}

我的读写方法所做的就是修改打开的文件所指向的初始结构Dev。无论我copy_to_user从我的结构是什么样的用户认为被写入到该设备并不管我copy_from_user的用户认为他们正在写。但是除了更改我的初始结构Dev之外,文件位置或偏移量的概念没有任何意义,除非它指向内核中某个任意结构或类型的缓冲内存的指针。多数民众赞成在我对文件偏移量的唯一解释…这是正确的吗?这是loff_t *offp这里所指的吗?

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)

(假设我的理解是正确的)当调用了一些诸如读/写之类的file_operation并且我没有*offp亲自设置时,loff_t * offp最初设置为什么?

如果在最后一个file_operation中offp =
some_arbitrary_address(因为我这样告诉我),那么当再次调用此操作时,offp将设置为什么?

如果我正在运行其他file_opens操作,它将设置为上次file_operation保留的状态,还是会保留使用的file_open操作的选项卡,并将*
offp替换为file_open使用的内容,会发生什么情况?

char设备的概念对我来说太抽象了,它看起来设备本身甚至不像文件那样存储信息,而是存储信息的驱动程序。我希望我已经解释了我的模糊感,并且会清理掉我似乎不清楚的所有内容。


阅读 816

收藏
2020-06-03

共1个答案

一尘不染

“参数loff_t”是一个“长偏移量”,即寻求立场相结合的疯狂多样性off_toff64_t等,使驾驶者可以只使用参数loff_t,而不是担心。

当您进入驱动程序时,指针本身指向用户提供的偏移量(假设它是用户代码来执行驱动程序访问,从技术上讲内核可以提供自己的偏移量,但是用户的情况就是要考虑的情况)通过lseekllseeklseek64等等,然后通过普通的读写操作。考虑一下常规磁盘文件的情况:当您首次创建open文件时,您(作为用户)将获得内核以提供一个数据结构,该数据结构可跟踪您在文件中的当前位置,因此,如果您readwrite某些字节,下一个readwrite从您上次停站的地方接站。

此外,如果你dup文件描述符,或做通过(例如)的等效forkexec运行命令的序列而言,该寻找位置由所有继承进程共享。因此,在shell提示符下,命令:

(prog1; prog2; prog3) > outputfile

创建一个输出文件,然后dup将描述符传递给这三个程序,以便prog2写入的输出在的输出之后立即进入该文件prog1,而输出的结果prog3紧随其他两个之后—都是因为所有三个单独的进程共享相同的基础内核数据结构具有相同的内部loff_t

这同样适用于设备驱动程序文件。调用读取和写入函数时,您会收到用户提供的“当前偏移量”,并且可以(并且应该)根据需要对其进行更新…假设有任何需要(例如,您想为用户提供常规文件的外观,包括在读取和写入时偏移量会移动的事实)。如果设备在逻辑上应用了查找偏移,则可以在此处使用它。

当然,设备驱动程序还有很多,这就是为什么在此书(qv)上有整本书的章节。:-)

2020-06-03