我写了一个Linux的内核模块,当我该模块作为device时,当要去写入函数时,dmesg循环打印"Write!,为什么呢?代码如下:
#include <linux/types.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h> /* copy_to_user */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("author");
MODULE_DESCRIPTION("module demo");
//-----------------------------------------------------------------------------
// Parameters
//-----------------------------------------------------------------------------
#define MODULE_NAME "fakemodule"
#define CLASS_NAME "modcls"
#define NUM_MINORS 1
#define SUCCESS 0
static dev_t devno;
typedef struct {
struct cdev cdv;
struct class *cls;
struct device *dev;
} fakemodule_t;
fakemodule_t mymod;
//-----------------------------------------------------------------------------
// File Operations
//-----------------------------------------------------------------------------
int fakemodule_open(struct inode *inode, struct file *filp)
{
printk("Opened!\n");
return SUCCESS;
}
int fakemodule_release(struct inode *inode, struct file *filp)
{
printk("Closed!\n");
return SUCCESS;
}
ssize_t fakemodule_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
printk("Write!\n");
return 0;
}
ssize_t fakemodule_read(struct file *filp, char * buf, size_t count, loff_t *f_pos)
{
printk("Read!\n");
return 0;
}
struct file_operations fakemodule_fops = {
owner: THIS_MODULE,
read: fakemodule_read,
write: fakemodule_write,
open: fakemodule_open,
release: fakemodule_release
};
//-----------------------------------------------------------------------------
// Module Init/Exit
//-----------------------------------------------------------------------------
static int __init fakemodule_init(void)
{
int retval = SUCCESS;
//Request a set of character device numbers
printk("Registering Driver\n");
if ((retval = alloc_chrdev_region(&devno, 0, NUM_MINORS, MODULE_NAME)) != 0)
{
printk("Failed to create chrdev region");
goto init_fail;
}
mymod.cls = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(mymod.cls))
{
retval = PTR_ERR(mymod.cls);
printk("Failed to create module class\n");
goto probe_class_fail;
}
if (IS_ERR(mymod.dev))
{
retval = PTR_ERR(mymod.dev);
printk("Failed to create module class device\n");
goto probe_device_class_fail;
}
//Initialize each of the possible character devices
cdev_init(&mymod.cdv, &fakemodule_fops);
if ((retval = cdev_add(&mymod.cdv, devno, 1)) != 0){
printk("Error %d while trying to add cdev\n", retval);
goto probe_cdev_init_fail;
}
printk("Driver Initialized!\n");
return SUCCESS;
//Handle Fail
probe_cdev_init_fail:
device_destroy(mymod.cls, MKDEV(MAJOR(devno), 0));
probe_device_class_fail:
class_destroy(mymod.cls);
probe_class_fail:
unregister_chrdev_region(devno, 1);
init_fail:
return retval;
}
static void __exit fakemodule_exit(void)
{
//int major = 0;
printk("Cleanup Module\n");
printk("Unregistering Character Driver\n");
cdev_del(&mymod.cdv);
printk("Give back all the numbers we requested\n");
unregister_chrdev_region(devno, NUM_MINORS);
printk("Remove the class driver");
device_destroy(mymod.cls, MKDEV(MAJOR(devno), 0));
printk("Release the class");
class_unregister(mymod.cls);
class_destroy(mymod.cls);
printk("Finished Cleanup Module, Exiting\n");
return;
}
module_init(fakemodule_init);
module_exit(fakemodule_exit);
根据您给出的代码,您的内核模块实现了一组字符设备操作。其中,在fakemodule_write
函数中,每次有写入操作发生时,都会通过printk
输出"Write!"到内核日志。
如果您在dmesg
看到连续打印的"Write!",那么有以下可能的原因:
-
高频率的写请求:可能有一个或多个进程/应用正在频繁地写入到您的字符设备。
-
错误的设备路径:有些程序可能不小心或错误地反复写入到您的设备路径。
-
返回值问题:在
fakemodule_write
函数中,您返回了0,表示一次写入操作没有实际写入任何数据。这可能会导致调用write
的用户空间程序认为没有数据被写入,因此它可能会不断重试。您应该返回count
(实际希望写入的字节数)或在出错时返回一个负数的错误码。
解决建议:
-
检查写请求的来源:您可以通过
lsof
或其他工具检查哪些进程正在使用您的字符设备。这可以帮助您确定是否有进程频繁地写入。 -
返回适当的值:在
fakemodule_write
函数中返回count
以表示已成功处理的字节数。这样用户空间的程序就知道它的写操作已经完成。
ssize_t fakemodule_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
printk("Write!\n");
return count; // indicate all bytes are "handled"
}
- 添加更多的日志输出:您可以在
fakemodule_write
函数中添加更多的日志,以帮助您更好地理解写请求的内容和来源。
最后,请确保您的模块正确处理并防止潜在的资源竞争或多线程问题,这些问题也可能导致异常的行为。