我正在为字符设备驱动程序编写基本的设备驱动程序模块。我想要以下行为:当我将使用cat /dev/scull
从设备文件中读取时,我应该得到设备被打开的次数。为此,我使用变量计数,并在调用开放函数时增加它。我将这个变量存储在私有结构中。我遇到的问题是读取功能
struct scull_dev{
int x; /*Private data members*/
struct cdev cdev; /*This is character device structure*/
};
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct scull_dev *dev = filp->private_data;
pr_info("You have opened device %d timesn",dev->x);
return sizeof(dev->x);
}
打印语句"您已读取设备%d次"正在打印无限次。我必须按Ctr+D
才能停止。
我希望输出到cat以及日志文件中。
注意:您得到的输出是无限的,因为您总是返回sizeof
。而且,您没有将数据复制到cat
的代码。
好吧,我已经把我认为你需要的东西编好了[请原谅一些无端的风格清理]。注意:我没有构建它。我已经对它进行了一些注释,所以这应该会让你开始:
struct scull_dev {
int x; /*Private data members*/
int rdpend; // 1=partial read in progress
int bufoff; // current offset within buffer
int buflen; // remaining length to transfer
char buf[100]; // buffer with text to output
struct cdev cdev; /*This is character device structure*/
};
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
struct scull_dev *dev = filp->private_data;
ssize_t curlen;
long err;
// NOTES:
// (1) rdpend _must_ be cleared in the device close (and/or) device
// open -- we only want _one_ output line per invocation
// (2) _after_ you get this working, you might move _this_ code block
// to the open routine (i.e. the rdpend would not be necessary)
// (3) leaving it here makes the pr_info and cat output appear closer in
// time
do {
// only output a single line per open
if (dev->rdpend)
break;
dev->rdpend = 1;
dev->buflen = snprintf(dev->buf,sizeof(dev->buf),
"You have opened device %d timesn",dev->x);
pr_info("%s",dev->buf);
dev->bufoff = 0;
} while (0);
// get length and handle user short read
// [possibly less than we have--(e.g.) caller's count could be (say) 10
curlen = dev->buflen;
if (curlen > count)
curlen = count;
do {
// nothing left to output
if (curlen <= 0)
break;
err = copy_to_user(buf,dev->buf + dev->bufoff,curlen);
// probably an access violation or segmentation fault, etc.
if (err < 0) {
curlen = err;
break;
}
// creep through the buffer
dev->buflen -= curlen;
dev->bufoff += curlen;
} while (0);
return curlen;
}
提醒:不要忘记在打开和/或关闭时清除rdpend
。