2016-03-18 6 views
1

Я пытаюсь сделать некоторые программы для модуля ядра/пользовательского уровня. Я получил предложение ранее использовать fdopen(), который работал хорошо, но я выяснил, что я должен использовать open(), read() и write() вместо этого. Я прочитал страницы руководства для них и подумал, что я правильно конвертировал fopen, fgets, fputs, и моя программа компилируется, но я не получаю желаемый результат.Что я делаю неправильно с read() и write()?

У меня есть таймер, если я вхожу ./userprogram -s (int) (name), например. ./userprogram -s 5 hello, через 5 секунд он будет печатать hello на консоли, общаясь с моим модулем ядра. После того, как я переключился на эти новые функции, вместо этого он печатает /lib/ld-uClibc.so.0 (и, кажется, дожидается ~ 5 секунд, несмотря на это). Мне также нужно изменить способ работы кода уровня ядра? Я думал, что просто смогу изменить программу уровня пользователя, и модуль ядра будет продолжать работать так, как раньше. Вот что я пробовал с оригинальным кодом, который работал закомментированным:

// open file 
int pFile; 
pFile = open("/dev/mytimer", O_RDWR); 
if (pFile < 0) { 
    fprintf (stderr, "mytimer module isn't loaded\n"); 
    return 1; 
} 

// Check if timer set 
if (argc >= 4 && strcmp(argv[1], "-s") == 0) { 
    lenNum = strlen(argv[2]); 
    lenName = strlen(argv[3]); 
    char *ptr = malloc(lenNum+lenName+4); 
    strncat(ptr, argv[1], 2);//flag 
    strncat(ptr," ", 1); 
    strncat(ptr, argv[2], lenNum);//timer length 
    strncat(ptr," ", 1); 
    strncat(ptr, argv[3], lenName);//message 

    /* fputs(ptr, pFile); */ 
    write(pFile, ptr, sizeof(ptr)); 
    /* 
    while (fgets(line, 256, pFile) != NULL) { 
     printf("%s", line); 
    } */ 
    while (read(pFile, ptr, sizeof(ptr)) != 0) { 
     printf("%s", line); 
    } 

Любые предложения приветствуются.

+0

Вы уже использовали 'open()', по крайней мере, если вы получали поток через 'fdopen()'. –

+0

Я думаю, что я делал что-то вроде 'int file = open()' then 'FILE * pFile = fdopen (файл," r + ");' Затем использовал 'open()' on 'file' и' fgets() 'и 'fputs()' on 'pFile'. – Austin

+0

'fdopen()' связывает поток с открытым файловым дескриптором. Вы должны каким-то образом получить файловый дескриптор, и это обычно происходит через 'open()'. Конечно, вы можете 'fdopen()' один из стандартных номеров файлов, но это бессмысленно, потому что вы уже бесплатно получаете 'stdin',' stdout' и 'stderr'. –

ответ

4

[I], что я преобразовал FOPEN, fgets, fputs к ним правильно

... но вы ошиблись. Не существует однострочного эквивалента write(), равного fputs(), и нет однострочного read() на основе эквивалента fgets(). Функции ввода-вывода, основанные на потоке, выполняют большую работу, которую вы должны выполнять самостоятельно, когда используете низкоуровневые read() и write().

Некоторые различия являются:

  • read() не обеспечивает завершение строки. Вы должны сделать это сами.
  • write() не обращает внимания на завершение строки. Если вы хотите, чтобы он остановился на строковых терминаторах, вы должны контролировать это через количество байтов, которое вы просите передать.
  • read() и write() ни один из них не может передать полное количество байтов, запрошенных в одном вызове. Если вы хотите передать определенное количество байтов, вы должны быть готовы к циклу.
  • read() не останавливается автоматически на любом конкретном символе, включая новую строку
  • Большинство потоков обеспечивают буферизацию, невидимую для вас. Если вы хотите буферизировать свои read() и write() s, тогда вам придется обрабатывать его самостоятельно (но эти функции хорошо подходят для него).

В вашем конкретном случае, однако, вы также совершили семантическую ошибку. Третий аргумент как write(), так и read() - это максимальное количество передаваемых байтов - часто размер буфера - но sizeof(ptr) - это размер самого указателя, а не размер пространства, на которое он указывает.

+0

Мне показалось, что я читал, что 'fputs()' не завершает работу, а 'puts()' делает? Наверное, я, возможно, тоже прочитал это неправильно. Я запутался в твоем третьем пункте, не могли бы вы объяснить это немного больше? Я изменил 'sizeof()' на 'strlen()', как предлагал @Jens, и, похоже, он исправил часть проблемы, но я все еще получаю некоторые странные символы. – Austin

+2

@Austin 'puts()' выводит новую строку после содержимого строки, а 'fputs()' нет, но оба обращают внимание на завершение строки. Кроме того, вы не могли бы говорить о «содержимом струны» в первую очередь. Терминатор строки сообщает обоим, где заканчивается содержимое. С другой стороны, функция 'write()' не делает различий, основанных на значениях байтов, которые вы ему представляете. –

3

sizeof(ptr), вероятно, 4 или 8 (то есть sizeof(char *)), а не длина данных, которые вы хотите записать.

И способ, которым вы строите данные, чрезвычайно громоздким. Почему бы не использовать один sprintf(), или, если у вас есть, asprintf(), что даже mallocs память:

char *ptr; 
int i; 

i = asprintf (&ptr, "%s %s %s", argv[1], argv[2], argv[3]); 
write (pFile, ptr, i); 
free(ptr); 

Это не сладко и кратким?

+0

Я не знал о 'asprintf()', thanks;) – Austin

+0

@Austin Это расширение по ISO C и POSIX, найденное во многих Unix-системах. – Jens

+0

@Jens, это мило и лаконично, да, но не совсем правильно. Он не учитывает возможность короткого 'write()'. Он также не выполняет никаких проверок ошибок, но в этом отношении он параллелен попытке OP. –

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

  • Нет связанных вопросов^_^