Что я делаю не так с read() и write()?

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

У меня есть таймер, где, если я вхожу ./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);
    }   

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

2 ответа

Решение

[Я] думал, что я правильно преобразовал fopen,fgets,fputs в эти

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

Некоторые из различий:

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

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

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

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

char *ptr;
int i;

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

Разве это не так мило и лаконично?

Другие вопросы по тегам