Я новичок в Linux модуле ядра. Я изучаю модуль драйвера чар на основе веб-курса. У меня есть очень простой модуль, который создает /dev/chardevexample
, и у меня есть вопрос для моего понимания:
Когда я выполняю echo "hello4" > /dev/chardevexample
, я вижу, что write
выполняется ровно один раз, как и ожидалось. Однако, когда я делаю cat /dev/chardevexample
, я вижу чтение выполненное два раза.
Я вижу это как в своем коде, так и в материале курса. Все данные были возвращены в первом read()
, так почему cat
вызывает его снова?
Все, что я сделал до сих пор, таково:
insmod chardev.ko
загрузить мой модуль echo "hello4" > /dev/chardevexample
. Это запись, и я вижу, что это происходит ровно один раз в dmesg cat /dev/chardevexample
. Это чтение, и dmesg
показывает, что это происходит дважды. Я сделал strace cat /dev/chardevexample
, и я действительно вижу, что вызов функции вызывается дважды для чтения. Также есть запись между
read(3, "hello4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072) = 4096
write(1, "hello4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096hello4) = 4096
read(3, "", 131072)
dmesg
после чтения (команда cat)
[909836.517402] DEBUG-device_read: To User hello4 and bytes_to_do 4096 ppos 0 # Read #1
[909836.517428] DEBUG-device_read: Data send to app hello4, nbytes=4096 # Read #1
[909836.519086] DEBUG-device_read: To User and bytes_to_do 0 ppos 4096 # Read #2
[909836.519093] DEBUG-device_read: Data send to app hello4, nbytes=0 # Read #2
Фрагмент кода для чтение, запись и file_operations прилагается. Любое руководство поможет. Я много искал и не мог понять. Отсюда и пост.
/*!
* @brief Write to device from userspace to kernel space
* @returns Number of bytes written
*/
static ssize_t device_write(struct file *file, //!< File pointer
const char *buf,//!< from for copy_from_user. Takes 'buf' from user space and writes to
//!< kernel space in 'buffer'. Happens on fwrite or write
size_t lbuf, //!< length of buffer
loff_t *ppos) //!< position to write to
{
int nbytes = lbuf - copy_from_user(
buffer + *ppos, /* to */
buf, /* from */
lbuf); /* how many bytes */
*ppos += nbytes;
buffer[strcspn(buffer, "\n")] = 0; // Remove End of line character
pr_info("Recieved data \"%s\" from apps, nbytes=%d\n", buffer, nbytes);
return nbytes;
}
/*!
* @brief Read from device - from kernel space to user space
* @returns Number of bytes read
*/
static ssize_t device_read(struct file *file,//!< File pointer
char *buf, //!< for copy_to_user. buf is 'to' from buffer
size_t lbuf, //!< Length of buffer
loff_t *ppos)//!< Position {
int nbytes;
int maxbytes;
int bytes_to_do;
maxbytes = PAGE_SIZE - *ppos;
if(maxbytes >lbuf)
bytes_to_do = lbuf;
else
bytes_to_do = maxbytes;
buffer[strcspn(buffer, "\n")] = 0; // Remove End of line character
printk("DEBUG-device_read: To User %s and bytes_to_do %d ppos %lld\n", buffer + *ppos, bytes_to_do, *ppos);
nbytes = bytes_to_do - copy_to_user(
buf, /* to */
buffer + *ppos, /* from */
bytes_to_do); /* how many bytes*/
*ppos += nbytes;
pr_info("DEBUG-device_read: Data send to app %s, nbytes=%d\n", buffer, nbytes);
return nbytes;} /* Every Device is like a file - this is device file operation */ static struct file_operations device_fops = {
.owner = THIS_MODULE,
.write = device_write,
.open = device_open,
.read = device_read,};