Почему я получаю сообщение об ошибке при попытке "перехватить" мой драйвер char-устройства?
Я написал простой драйвер символьного устройства для Linux.
Это простая система хранения / извлечения сообщений, в которой сообщения хранятся в пространстве ядра.
Я должен быть в состоянии сделать что-то вроде этого:
echo "message 1" > /dev/mydevice
а затем получить сообщение с
cat /dev/mydevice
Сообщения хранятся в очереди.
Когда я пытаюсь получить сообщение, которое я жестко запрограммировал для тестирования (сообщение "привет"), я получаю следующий вывод из командной строки:
cat /dev/mydevice
hellocat: /dev/mydevice: Resource temporarily unavailable
Поэтому я получаю приветственное сообщение, как и предполагалось, но, очевидно, я делаю что-то не совсем правильно.
Вот функция, которая обрабатывает чтение устройства.
static ssize_t device_read(struct file *filp, char *buffer,
size_t length, loff_t * offset) {
unsigned long result;
int message_size;
struct message_list* message = pop_message(&global_message_list);
if (!message) return -EAGAIN;
message_size = message -> message_length;
result = copy_to_user(buffer, message -> message, message_size);
printk(KERN_ALERT "res: %lu, msg_size: %d, len: %d\n", result, message_size, length);
if (result == 0) return message_size;
else return message_size - result;
}
1 ответ
cat
коммунальные вызовы read
более одного раза для каждого файла, пока он не достигнет EOF (что обозначается read
возвращая 0).
Это потому, что не все данные могут быть доступны сразу. Если файл больше чем cat
s внутренний буфер, он, конечно, должен будет вызвать read
несколько раз, чтобы получить полные данные. Даже если число байтов, возвращаемых read
меньше, чем длина буфера, его нужно будет вызвать read
снова в случае, если больше данных будет доступно позже (как это может быть в случае, если ввод TTY или труба). Поэтому вам нужно вернуть 0, чтобы получить cat
думать, что это в конце файла и прекратить чтение.
(Более подробно о том, как cat
работает, вы можете проверить исходный код, и safe_read
функция.)
Простой способ справиться с этим - поместить сообщение нулевой длины в вашу очередь после каждого "реального" сообщения, чтобы следующее read
вернет EOF. Тем не менее, это не будет работать правильно, если у вас есть несколько читателей одновременно; в этом случае один читатель может прочитать сообщение, затем другой читает EOF, затем первый читает другое сообщение, так что один читатель получает два сообщения, а другой - ноль. Вам и / или вашему инструктору решать, сделать ли ваше устройство безопасным для потоков.¹
Это также указывает на еще одну потенциальную проблему с вашим кодом, которую вы обрабатываете только частично: если у вас есть сообщение больше, чем буфер, переданный в read
, вы отбрасываете оставшуюся часть сообщения, а не сохраняете ее для следующего read
, Опять же, это может быть приемлемым недостатком или нет.
Not Я не уверен, возможно ли сделать его безопасным для потоков; это зависит от того, насколько хорошо вы можете различать разных читателей, и я не знаю достаточно о коде ядра или написании символьных устройств, чтобы сказать, возможно ли это.