Linux驱动开发 驱动程序的具体编写及出口入口函数解析,printk打印内核信息

举报
yd_274589494 发表于 2023/07/26 12:12:01 2023/07/26
【摘要】 @TOC 前言本文将带大家学习驱动程序的具体编写及出口入口函数解析。 一、出口函数入口函数解析每一个驱动程序都是含有出口函数和入口函数的,装载驱动的时候先调用入口函数,卸载驱动的时候则调用出口函数。入口出口函数的形式如下:static __init int hello_dev_init(void){ printk("%s %s %d\n", __FILE__, __FUNCTION__, _...

@TOC


前言

本文将带大家学习驱动程序的具体编写及出口入口函数解析。

一、出口函数入口函数解析

每一个驱动程序都是含有出口函数和入口函数的,装载驱动的时候先调用入口函数,卸载驱动的时候则调用出口函数。
入口出口函数的形式如下:

static __init int hello_dev_init(void)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);	
	return 0;
}

static __exit void hello_dev_exit(void)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}


module_init(hello_dev_init);
module_exit(hello_dev_exit);

module_init和module_exit的作业是将上面两个函数分别修饰为入口函数和出口函数,一般的函数我们不能随意指定他就是出口函数和入口函数,必须经过指定后才能认为他是入口函数和出口函数。

有同学可能会有疑惑为什么这两个函数前面要加__init和__exit呢?
其实__init和__exit就只是一个空的宏,入口函数和出口函数在整个过程中都只会调用一次,调用完后我们可以将其释放节省内存,使用这两个标识就可以达到这样的效果。
在这里插入图片描述

二、printk内核打印信息

在普通的程序中我们一般使用的是printf来输出打印信息,但是在Linux内核中要用printk来打印输出信息。
一般默认情况下内核的打印信息是没有打开的,我们需要将其打开。

cat /proc/sys/kernel/printk//查看设置值
echo 7       4       1      7 > /proc/sys/kernel/printk//打开内核打印信息

将内核的打印功能打开后我们就可以使用printk去打印输出信息了。

三、驱动程序的具体编写

1.确定主设备号
主设备号可以由我们自己指定,也可以由系统帮我们指定。

static int major = 0;

2.构造file_operations结构体

static struct file_operations hello_drv = {
	.owner	 = THIS_MODULE,
	.open    = hello_drv_open,
	.read    = hello_drv_read,
	.write   = hello_drv_write,
};

3.实现对应的open,read,write函数

static ssize_t hello_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 1;
}

static ssize_t hello_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 1;
}

static int hello_drv_open (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

4.注册驱动程序
在Linux中我们会经常听到注册这个词,注册其实就是将结构体添加进链表。

major = register_chrdev(0, "hello", &hello_drv);

5.编写入口函数

static int __init hello_init(void)
{
	int err;
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	major = register_chrdev(0, "hello", &hello_drv);  /* /dev/hello */


	hello_class = class_create(THIS_MODULE, "hello_class");
	err = PTR_ERR(hello_class);
	if (IS_ERR(hello_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "hello");
		return -1;
	}
	
	device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello"); /* /dev/hello */
	
	return 0;
}

6.编写出口函数

static void __exit hello_exit(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	device_destroy(hello_class, MKDEV(major, 0));
	class_destroy(hello_class);
	unregister_chrdev(major, "hello");
}

7.完善信息

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

总结

本篇文章的内容不多大家看完后有什么疑问可以留言。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。