内核常用函数

内核常用函数

printk 输出信息

这里使用了 printk 来输出信息,而不是 printf!因为在 Linux 内核中没有 printf 这个函数。printk 相当于 printf 的孪生兄妹,printf运行在用户态,printk 运行在内核态。在内核中想要向控制台输出或显示一些内容,必须使用printk 这个函数。不同之处在于,printk 可以根据日志级别对消息进行分类,一共有 8 个消息级别,这 8 个消息级别定义在文件 include/linux/kern_levels.h 里面,定义如下:

#define KERN_SOH  "\001" 
#define KERN_EMERG KERN_SOH "0"  /* 紧急事件,一般是内核崩溃 */
#define KERN_ALERT KERN_SOH "1"  /* 必须立即采取行动 */
#define KERN_CRIT  KERN_SOH "2"  /* 临界条件,比如严重的软件或硬件错误*/
#define KERN_ERR  KERN_SOH "3"  /* 错误状态,一般设备驱动程序中使用KERN_ERR 报告硬件错误 */
#define KERN_WARNING KERN_SOH "4"  /* 警告信息,不会对系统造成严重影响 */
#define KERN_NOTICE  KERN_SOH "5"  /* 有必要进行提示的一些信息 */
#define KERN_INFO  KERN_SOH "6"  /* 提示性的信息 */
#define KERN_DEBUG KERN_SOH "7"  /* 调试信息 */

一共定义了 8 个级别,其中 0 的优先级最高,7 的优先级最低。如果要设置消息级别,参考如下示例:

printk(KERN_EMERG "gsmi: Log Shutdown Reason\n");

上述代码就是设置“gsmi: Log Shutdown Reason\n”这行消息的级别为 KERN_EMERG。在具体的消息前面加上 KERN_EMERG 就可以将这条消息的级别设置为 KERN_EMERG。

如果使用 printk 的 时 候 不 显 式 的 设 置 消 息 级 别 , 那 么 printk 将 会 采 用 默 认 级 别MESSAGE_LOGLEVEL_DEFAULT,MESSAGE_LOGLEVEL_DEFAULT 默认为 4。在 include/linux/printk.h 中有个宏 CONSOLE_LOGLEVEL_DEFAULT,定义如下:

#define CONSOLE_LOGLEVEL_DEFAULT 7

CONSOLE_LOGLEVEL_DEFAULT 控制着哪些级别的消息可以显示在控制台上,此宏默认为 7,意味着只有优先级高于 7 的消息才能显示在控制台上。

这个就是 printk 和 printf 的最大区别,可以通过消息级别来决定哪些消息可以显示在控制台上。默认消息级别为 4,4 的级别比 7 高,所示直接使用 printk 输出的信息是可以显示在控制台上的。


内核和用户间的数据传递

copy_to_user()

因为内核空间不能直接操作用户空间的内存,因此需要借助 copy_to_user 函数来完成内核空间的数据到用户空间的复制。copy_to_user 函数原型如下:

static inline long copy_to_user(void __user *to, const void *from, unsigned long n)

参数 to 表示目的,参数 from 表示源,参数 n 表示要复制的数据长度。如果复制成功,返回值为 0,如果复制失败则返回负数。

copy_from_user

函数 copy_from_user 将 buf 中的数据复制到写缓冲区 writebuf 中,因为用户空间内存不能直接访问内核空间的内存,所以需要借助函数 copy_from_user 将用户空间的数据复制到 writebuf 这个内核空间中。


动态内存申请释放

kmalloc申请内存

	/* 申请内存 
	 * 如果使用的是 u32 *u32_array; 来表示数组 则需要申请内存
	 * 如果使用 u32 u32_array[8]; 则不需要申请内存
	 * 使用u32 u32_array[8]模式,前提是要知道要读取的属性有几个元素
	 */

u32_array = kmalloc(elem_num * sizeof(u32), GFP_KERNEL);
if(!u32_array){
    ret = -EINVAL;
    printk("malloc falied!\r\n");
    goto fail_malloc;
}

kfree释放内存

kfree(u32_array);

对Linux下常用头文件总结

Author@firestaradmin 2020年5月4日17:55:50

asm.current.h 定义全局项current ,其指向结构体struct task_struct

linux/sched.h 定义结构体task_struct ,只要包含此头文件即可引用当前进程

linux/modules.h 定义含有可装载模块需要的大量符号和函数

linux/init.h 定义初始化和清楚函数

linux/errno.h 定义错误编码

linux/stat.h 定义成员访问许可值

linux/sched.h 定义大部分内核API,包括睡眠函数以及各种变量声明

linux/version.h 定义内核版本信息

linux/moduleparam.h 定义用来创建模块的宏

linux/kernel.h 定义函数printf的内核代码

linux/types.h 定义dev_t ,岂作用是用来保存设备编号

linux/kdev_t.h 定义用来操作设备编号的宏

linux/fs.h 定义file_operations , file 等重要结构体,和inode结构

linux/cdev.h 定义字符设备struct cdev 结构体以及与其相关的一些辅助函数

linux/slab.h 定义内存管理的连个核心函数:*kmalloc kfree

asm/uaccess.h 定义访问用户缓冲区函数如:copy_from_user

linux/uio.h 定义iovec结构体

sys/syslog.h 定义syslogd可选值

linux/proc_fs.h 定义/proc 的模块

linux/seq_file.h 定义seq_file接口

asm/semaphore.h 定义信号量相关的东西

linux/rwsem.h 定义读取中/写入者信号量

linux/completion.h 定义complete 相关

linux/spinlock.h 定义spinlock 相关

asm/atomic.h 定义原子操作相关

asm/bitops.h 定义位操作相关(宏)

linux/seqlock.h 定义seqlock 相关

linux/rcupdate.h 定义RCU 相关(read_copy_update)

linux/ioctrl.h 定义ioctrl命令相关符号

asm/ioctrl.h 定义一些构造命令编号的宏

linux/kd.h 定义用来定义ioctrl命令的16位标量值(旧风格)

asm/uaccsee.h 定义access_ok函数(验证地址)

linux/capability.h 定义linux的全部权能操作

sys/sched.h 定义权能检查函数:capable(1C)

linux/wait.h 定义等待序列相关

linux/fcntl.h 定义I/O操作相关标志

linux/poll.h 定义poll和lelect相关

linux/param.h 定义与体系结构有关的常熟:HZ

linux/jiffies.h 定义jiffies计数器,只需包含<sys/sched.h>,会自动放入jiffies.h

linux/timex.h 定义定时相关

asm/msr.h X86专用头文件

linux/time/h 定义一些时间操作函数:do_gtetimeofday

linux/workqueue.h 定义struct workqueue_struct 结构体

linux/slab.h 定义*kmalloc(2C )函数

linux/gfp.h 定义分配内存参数标志

asm/pgtable.h 定义vmalloc(1C)可获得地址范围的连个宏

linux/percpu_counter.h 定义封装使用per_CPU变量来简历的简单整数计数器

linux/vmalloc.h 定义函数vmalloc(1C)

asm/io.h 定义I/O mapping等函数

linux/ioport.h 定义I/O 内存分配区域的接口

linux/sched.h 定义中断函数接口

linux/interrupt.h 定义中断相关

asm/page.h 定义页大小

asm/byteorder.h 定义字节序

linux/err.h 定义指针和错误值

linux/list.h 定义链表相关

linux/pci.h 定义数据传输访问配置空间函数

#include <linux/of_address.h> of_iomap()

Led字符设备驱动用到的

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <linux/uaccess.h>

#include <linux/io.h>

#include <linux/cdev.h>

#include <linux/device.h>

#include <linux/of.h>

#include <linux/of_address.h>

#include <linux/slab.h>