Olej писал(а):
P.P.S. Конечно, интересно бы довести примеры работы с read_proc_t функцией для разных случаев (нескольких последовательных коротких вызовов "по частям" + суммарным объёмом больше страницы 4Kb ... или 3Kb???) ... но это можно уже оставить "на свободное от основных занятий время"
Достаточно любопытные вещи вылазят...
(
"Неисповедимы дела Твои, Линус Торвальдс")
Маленькая программка mcat.c, уместная вообще ко всем примерам в /proc: подобна cat, но запрашивает в цикле чтений разовую длину порции, которую можно указать параметром запуска:
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "common.h"
static int get_proc( void ) {
char dev[ 80 ];
int df;
sprintf( dev, "/proc/%s", NAME_NODE );
if( ( df = open( dev, O_RDONLY ) ) < 0 ) {
sprintf( dev, "/proc/%s/%s", NAME_DIR, NAME_NODE );
if( ( df = open( dev, O_RDONLY ) ) < 0 )
printf( "open device error: %m\n" ), exit( EXIT_FAILURE );
}
return df;
}
int main( int argc, char *argv[] ) {
int df = get_proc(),
len = ( argc > 1 && atoi( argv[ 1 ] ) > 0 ) ?
atoi( argv[ 1 ] ) : LEN_MSG;
char msg[ LEN_MSG + 1 ] = "";
char *p = msg;
int res;
do {
if( ( res = read( df, p, len ) ) >= 0 ) {
*( p += res ) = '\0';
printf( "read + %02d bytes, input buffer: %s", res, msg );
if( *( p - 1 ) != '\n' ) printf( "\n" );
}
else printf( "read device error: %m\n" );
} while ( res > 0 );
close( df );
return EXIT_SUCCESS;
};
в "common.h" определены общие константы проекта, ну и оттуда mcat знает имена интересующих /proc/*, чтоб не набирать каждый раз...
А теперь
минимально-достаточный код функции чтения в модуле:
Код: Выделить всё
#include "common.h"
static ssize_t proc_node_read( char *buffer, char **start, off_t off,
int count, int *eof, void *data ) {
static char buf_msg[ LEN_MSG + 1 ] =
".........1.........2.........3.........4.........5.........6\n";
LOG( "read: %d (buffer=%p, off=%ld)", count, buffer, off );
strcpy( buffer, buf_msg );
LOG( "return bytes: %d%s", strlen( buf_msg ), *eof != 0 ? " ... EOF" : "" );
return strlen( buf_msg );
};
Всё!
Т.е. в упрощенчестве они дошли до того, что (при передаче объёма данных
<=3Kb) в качестве обработчика достаточно одной операции strcpy() ... никаких EOF, разбиения объёма передачи на порции запрашиваемого объёма, позиционирования начала каждой передачи...
Всё делается скрыто внутри kernel кода, который пересылает это в user-space.
Сами себя перемудрили ...
это бред!
А теперь как это корректно работает:
Код: Выделить всё
[olej@notebook proc]$ ./mcat 10
read + 10 bytes, input buffer: .........1
read + 10 bytes, input buffer: .........1.........2
read + 10 bytes, input buffer: .........1.........2.........3
read + 10 bytes, input buffer: .........1.........2.........3.........4
read + 10 bytes, input buffer: .........1.........2.........3.........4.........5
read + 10 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 01 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 00 bytes, input buffer: .........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ dmesg | tail -n50 | grep -v ^audit
! /proc/mod_node installed
! read: 10 (buffer=f32b1000, off=0)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=10)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=20)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=30)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=40)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=50)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=60)
! return bytes: 61
! read: 9 (buffer=f32b1000, off=61)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=61)
! return bytes: 61
- обратите внимание там на совершенно ... пикантный
запрос на 9 байт...
Код: Выделить всё
[olej@notebook proc]$ ./mcat 70
read + 61 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 00 bytes, input buffer: .........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ dmesg | tail -n6 | grep -v ^audit
! read: 70 (buffer=f1dfd000, off=0)
! return bytes: 61
! read: 9 (buffer=f1dfd000, off=61)
! return bytes: 61
! read: 70 (buffer=f1dfd000, off=61)
! return bytes: 61
Код: Выделить всё
[olej@notebook proc]$ ./mcat 3
read + 03 bytes, input buffer: ...
read + 03 bytes, input buffer: ......
read + 03 bytes, input buffer: .........
read + 03 bytes, input buffer: .........1..
read + 03 bytes, input buffer: .........1.....
read + 03 bytes, input buffer: .........1........
read + 03 bytes, input buffer: .........1.........2.
read + 03 bytes, input buffer: .........1.........2....
read + 03 bytes, input buffer: .........1.........2.......
read + 03 bytes, input buffer: .........1.........2.........3
read + 03 bytes, input buffer: .........1.........2.........3...
read + 03 bytes, input buffer: .........1.........2.........3......
read + 03 bytes, input buffer: .........1.........2.........3.........
read + 03 bytes, input buffer: .........1.........2.........3.........4..
read + 03 bytes, input buffer: .........1.........2.........3.........4.....
read + 03 bytes, input buffer: .........1.........2.........3.........4........
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5.
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5....
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5.......
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 01 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 00 bytes, input buffer: .........1.........2.........3.........4.........5.........6
Код: Выделить всё
[olej@notebook proc]$ cat /proc/mod_node
.........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ cat /proc/mod_node
.........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ cat /proc/mod_node
.........1.........2.........3.........4.........5.........6
Тому, кто понимает толк в извращениях, должно понравиться то, что я показал
А в сухом остатке:
- если из модуля нужно вычитать <3Kb, то делается это простым strcpy() ...
- а если нужно вычитать >3Kb (но не говорит ли это о симптомах мразма?
), то нужно это делать совсем другими способами...