Linux设备驱动程序(第三版)第四章示例驱动程序

Linux设备驱动程序(第三版) 作者科波特(Corbet, j.)书本的示例代码比较零乱,而且网站上给的示例代码是旧版或者是比较完整的代码,且没有单独成章。初学者学习起来比较困难,所以笔者分享一下在学习过程中调试过的模块,供有需要的读者参阅。由于侧重书本每章的知识,所以模块仅反映每章的知识点,不是一个全面的驱动模块,但对学习驱动的编写可能比看书本本身网站提供的代码会更有侧重点。仅仅是每一章相对前一章增加一些代码,而不是一个全面的代码。希望能够交流学习。也可以通过 https://gitee.com/sanzhouzi/ldd3ex.git 下载, 其他章节的代码不再一一写文章显示。直接放到gitee仓库中。

第四章主要是说如何调试内核驱动代码,其中包括增加debug宏,在proc目录下创建自己的文件。增加的代码如下:

scull/main.c

#include <linux/proc_fs.h>
#include <linux/seq_file.h>

#ifdef SCULL_DEBUG

/*page 88*/
int scull_read_procmem(char *buf, char **start, off_t offset, 
				int count, int *eof, void *data)
{
	int i, j, len = 0;
	int limit = count - 80;
	for (i = 0; i < scull_nr_devs && len <= limit; i++) {
		struct scull_dev *d = &sculldev[i];
		struct scull_qset *qs = d->data;
		if (down_interruptible(&d->sem))
			return -ERESTARTSYS;
		len += sprintf(buf+len, "\nDevice %i: qset %i, q %i, sz %li\n",
				i, d->qset, d->quantum, d->size);
		for (; qs && len <= limit; qs = qs->next) {
			len += sprintf(buf + len, " item at %p, qset at %p\n",
						qs, qs->data);
			if (qs->data && !qs->next)
				for (j = 0; j < d->qset; j++) {
					if (qs->data[j])
						len += sprintf(buf + len,
							"    %4i: %8p\n", 
							j, qs->data[j]);
				}
		}
		up(&sculldev[i].sem);
	}
	*eof = 1;
	return len;
}

/*page 90*/
static void *scull_seq_start(struct seq_file *s, loff_t *pos)
{
	if (*pos >= scull_nr_devs)
		return NULL;
	return sculldev + *pos;
}

/*page 91*/
static void *scull_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
	(*pos)++;
	if (*pos >= scull_nr_devs)
		return NULL;
	return sculldev + *pos;
}

/*page 91*/
static void scull_seq_stop(struct seq_file *sfile, void *v)
{

}

/*page 92*/
static int scull_seq_show(struct seq_file *s, void *v)
{
	struct scull_dev *dev = (struct scull_dev *)v;
	struct scull_qset *d;
	int i;
	if (down_interruptible(&dev->sem))
		return -ERESTARTSYS;
	seq_printf(s, "\nDevice %i, qset %i, q %i, sz %li\n",
		(int)(dev - sculldev), dev->qset, dev->quantum, dev->size);
	for (d = dev->data; d; d = d->next) {
		seq_printf(s, " item at %p, qset at %p\n", d, d->data);
		if (d->data && !d->next)
			for (i = 0; i < dev->qset; i++) {
				if (d->data[i])
					seq_printf(s, "    %4i: %8p\n", 
							i, d->data[i]);
			}
	}
	up(&dev->sem);
	return 0;
}

static struct seq_operations scull_seq_ops = {
	.start = scull_seq_start,
	.next = scull_seq_next,
	.stop = scull_seq_stop,
	.show = scull_seq_show,
};

static int scull_proc_open(struct inode *inode, struct file *file)
{
	return seq_open(file, &scull_seq_ops);
}

static struct file_operations scull_proc_ops = {
	.owner = THIS_MODULE,
	.open = scull_proc_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = seq_release
};

static void scull_create_proc(void)
{
	struct proc_dir_entry *entry;
	/*page 89*/
	create_proc_read_entry("scullmem", 0, 
			NULL, scull_read_procmem, NULL);

	/*page 93*/
	entry = create_proc_entry("scullseq", 0, NULL);
	if (entry)
		entry->proc_fops = &scull_proc_ops;
}

static void scull_remove_proc(void)
{
	remove_proc_entry("scullmem", NULL);
	remove_proc_entry("scullseq", NULL);
}

#endif /*SCULL_DEBUG*/

/**********************************************/

static int __init scull_init(void)增加:

#ifdef SCULL_DEBUG
	scull_create_proc();
#endif /*SCULL_DEBUG*/

static void scull_exit(void)增加:

#ifdef SCULL_DEBUG
	scull_remove_proc();
#endif /*SCULL_DEBUG*/

scull/scull.h



#undef PDEBUG
#ifdef SCULL_DEBUG
#ifdef __KERNEL__
#define PDEBUG(fmt, args...) printk(KERN_NOTICE "scull: " fmt, ##args);
#else
#define PDEBUG(fmt, args...) fprintf(stderr, fmt, ##args)
#endif
#else
#define PDEBUG(fmt, args...) 
#endif

#undef PDEBUGG
#define PDEBUGG(fmt, args...)

scull/Makefile

DEBUG = y

ifeq ($(DEBUG), y)
	DEBFLAGS = -O -g -DSCULL_DEBUG
else
	DEBFLAGS = -O2
endif

EXTRA_CFLAGS += $(DEBFLAGS)


clean:
	rm -fr *.o *.ko *.mod.c *.mod.o *.order *.symvers
	

具体参见代码仓库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值