2016-01-14 2 views
0

Я создал файл под proc для чтения в строке, но вместо использования seq_file-реализации я могу прочитать его с помощью метода ssize_t (* read) в file_operations. Является ли этот подход неправильным?Использование функции ssize_t (* read) вместо реализации seq_file

Не могли бы вы объяснить, в каких ситуациях лучше использовать реализацию seq_file?

ssize_t my_proc_read(struct file *file, char __user *buffer, size_t count, loff_t *offset) 
    { 
     printk(KERN_INFO "loff_t *offset = %lld\n", *offset); 
     printk(KERN_INFO "count = %lu\n", count); 

     /* comment below two lines and check what happens. If we don't return 
     0 it means there is still some data and read is called repeatedly. */ 
     if((int)*offset >= ARRAY_LEN) 
     return 0; 
     *offset += ARRAY_LEN; 

    return sprintf(buffer, "%s\n", param); 
} 

Также на выходе я всегда получаю счет 131072, почему?

[ 7317.855146] loff_t *offset = 131073 
[ 7317.855149] count = 131072 
+0

И ** как вы создаете файл ** с помощью этой '.read' функции? Кроме того, неправильный доступ к буферам '__user' * напрямую * (что также выполняется с помощью' sprintf'): вы должны использовать 'copy_to_user' /' copy_from_user'. – Tsyvarev

+0

Этот файл создается в/proc с помощью функции proc_create из linux/proc_fs.h – anukalp

+0

Хм, и как вы получаете доступ к этому файлу из пользовательского пространства? Используя 'cat' или какую-то рукописную программу C? – Tsyvarev

ответ

1

seq_file полезна для файлов, которые содержание не хранится где-то, но генерируется на лету, когда пользователь нуждается. Это может быть генерация с использованием единственного формата строки (например, %s\n в вопросительном столбце) или комбинирования кусков разных или одинаковых типов.

При использовании функции seq_file, писатель кода не беспокоится о размере буфера для чтения, смещении текущего файла и доступе к __user данных с copy_to_user(). Вместо этого концентрируется на создании файла, как будто это поток неограниченного размера. Все остальное обрабатывается автоматически seq_file.

Например, приведенный пример может быть implememted с помощью seq_file следующего образом:

int param_show(struct seq_file *m, void *v) 
{ 
    (void)v; /* Unused */ 
    seq_printf(m, "%s\n", param); /* Just generate content of the "file" */ 
    return 0; 
} 

int my_proc_open(struct inode *inode, struct file *filp) 
{ 
    return single_open(filp, &param_show, NULL); 
} 

const struct file_operations my_proc_ops = { 
    .owner = THIS_MODULE, 
    .open = &my_proc_open, 
    .read = &seq_read 
}; 

Для сравнения, та же функциональность чтения реализована непосредственно:

ssize_t my_proc_read(struct file *file, char __user *buffer, size_t count, loff_t *offset) 
{ 
    ssize_t ret; 
    size_t param_len = strlen(param); 

    /* Write to buffer everything except terminating '\n' */ 
    ret = simple_read_from_buffer(buffer, count, offset, param, param_len); 
    /* But processing of additional '\n' is much more complex */ 
    if (ret >= 0 && ret < (ssize_t)count && *offset == param_len) { 
     char ch = '\n'; 
     int err = put_user(buffer + ret, &ch); /* Try to append '\n' */ 

     if (!err) { 
      /* Success */ 
      ++ret; 
      ++(*offset); 
     } else if (!ret) { 
      /* Fail and nothing has been read before */ 
      ret = err; 
     } 
    } 

    return ret; 
} 

const struct file_operations my_proc_ops = { 
    .owner = THIS_MODULE, 
    .read = &my_proc_read 
}; 

Как можно видеть, при чтении готового содержания params - однострочный (используется вспомогательный simple_read_from_buffer), дополнительный \n, который должен быть сгенерирован, делает реализацию намного сложнее ,

Минусом seq_file является его Perfomance: содержание, генерируется в .show функции не кэшируются, поэтому каждый последующий read() системный вызов требует .show называться снова. Кроме того, для создания содержимого файла используется внутренний буфер, и этот буфер должен быть выделен в кучу.

Но в большинстве случаев файлы, созданные на лету, небольшие и/или редко читаются и/или не критичны по производительности. Так что seq_file подходит для таких файлов практически во всех случаях.

Смежные вопросы