Что я делаю не так с 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);
Разве это не так мило и лаконично?