• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
又见炊烟升起
      新随笔    联系   管理    订阅  订阅

嵌入式linux开发guide

目录
  • 编写驱动程序的套路模板
  • 排查内存问题
    • 一个Linux内核模块的通用模板通常包括以下部分:
    • null

编写驱动程序的套路模板

(1) 确定主设备号,使用下列宏则可以通过主设备号和次设备号生成dev_t:

MKDEV(int major, int minor)

(2) 定义自己的 file_operations 结构体 
(3) 实现对应的 drv_open/drv_read/drv_write 等函数,填入 file_operations 结构体 
(4) 注册字符设备 - 把 file_operations 结构体告诉内核,使用register_chrdev()/register_chrdev_region(),或者alloc_chrdev_region()+cdev_alloc()+cdev_init()+cdev_add()
(5) 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数 
(6) 其他完善:提供设备信息,自动创建设备节点:
class_create()创建/sys/class/xxx 节点
device_create()创建设备节点/dev/xxx
sysfs_create_group()创建sysfs,即/sys/devices/xxx 节点(比如M57的:
/sys/devices/platform/smb/2900e000.virtio_i2c8/virtio92/i2c-8/8-0029/camera_D_parameter
或者/sys/bus/i2c/devices/i2c-8/8-0029/camera_D_parameter,两者是等效的)
proc_create_data()创建procfs,即/proc/driver/xxx 节点

(7) 卸载驱动程序时,按照有入口函数就应该有出口函数的原则:
class_create()对应的class_destroy()
device_create()对应的device_destroy()
register_chrdev()对应的unregister_chrdev()
cdev_init()对应的cdev_del()
alloc_chrdev_region()对应的unregister_chrdev_region()

(8)GPIO
输出
devm_gpio_request_one()
https://www.kernel.org/doc/html/latest/driver-api/gpio/index.html?highlight=gpio_request#c.devm_gpio_request_one
gpio_direction_output()
输入

gpio_direction_input()

int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, const char *devname, void *dev_id)
https://www.kernel.org/doc/html/latest/core-api/genericirq.html?highlight=request_threaded_irq#c.request_threaded_irq
(9)中断处理:
gpio_is_valid(g_cam_gpio_status.cam_avm_lock_status);
cam_avm_lock_irq = gpio_to_irq(g_cam_gpio_status.cam_avm_lock_status);
request_threaded_irq(cam_avm_lock_irq, NULL,cam_avm_lock_on_isr, irq_flags, "avm_lock_status", NULL);

(10)复位处理:硬复位一般重新上电没有问题;但是软复位需要考虑外设的复位,否则可能有故障(比如外设配置了新地址,cpu仍然使用默认地址读写外设,导致找不到外设),需要做到reset键把必要的外设芯片都重启了,避免外设芯片一直上电,导致故障时reset后仍然有故障(类似摄像头的寄存器配置错误的故障)


devm_kzalloc()
devm_clk_get
devm_gpio_request_one
sysfs_create_group(struct kobject *kobj,const struct attribute_group *grp)

排查内存问题

cat /proc/meminfo
cat /proc/zoneinfo
cat /proc/sys/vm/lowmem_reserve_ratio
cat /proc/buddyinfo
top -o %MEM

一个Linux内核模块的通用模板通常包括以下部分:

头文档:在模块的开头,通常包含必要的头文档,例如#include <linux/module.h>和#include <linux/kernel.h>等。
模块定义:使用module_LICENSE("GPL")宏声明模块的许可证,例如GPL。
模块参数:使用module_param宏定义模块参数,例如module_param(param_name, param_type, perm_attr)。其中,param_name是参数名称,param_type是参数类型,perm_attr是参数的访问权限。
模块导出函数:使用module_init(init_func)和module_exit(exit_func)宏定义模块的初始化和退出函数。其中,init_func是模块初始化函数,exit_func是模块退出函数。
模块描述:使用MODULE_DESCRIPTION(description)宏声明模块的描述信息。
模块参数列表:使用__param宏定义模块参数列表,例如__param(param_name, param_type)。
模块导出符号:使用EXPORT_SYMBOL(symbol)宏导出内核符号,例如EXPORT_SYMBOL(my_function)。
结束符号:使用MODULE_LICENSE("GPL")宏结束模块许可证声明。
以下是一个简单的Linux内核模块的通用模板示例:

#include <linux/module.h>  
#include <linux/kernel.h>  
  
MODULE_LICENSE("GPL");  
  
MODULE_DESCRIPTION("My Module");  
  
module_param(param_name, param_type, perm_attr);  
  
__param(another_param, another_type);  
  
EXPORT_SYMBOL(my_function);  
  
static int __init my_module_init(void) {  
    // Initialization code here  
    return 0;  
}  
  
static void __exit my_module_exit(void) {  
    // Exit code here  
}  
  
module_init(my_module_init);  
module_exit(my_module_exit);

分析Linux内核执行时间过长的原因可以涉及多个方面。以下是一些常见的分析和调试步骤:

查看系统负载和性能指标:使用top、htop、vmstat、iostat等命令查看系统的CPU使用率、内存使用情况、磁盘IO等,以了解是否存在资源瓶颈。
检查进程状态和日志:使用ps、top等命令查看进程状态,并检查相关日志以确定是否有某个进程或线程占用了过多的CPU时间。
检查CPU占用情况:使用perf、top等工具检查CPU占用情况,找出最耗时的内核函数或线程。
分析系统调用:使用strace等工具跟踪进程的系统调用,以了解其在执行期间进行了哪些操作。
检查内核配置:检查内核配置文档(如/boot/config-*)以确定是否启用了某些可能影响性能的选项。
分析内核模块:检查加载的内核模块以及相关的配置,确定是否有某个模块导致了性能问题。
检查硬件问题:如果可能,检查硬件(如CPU、内存、磁盘等)是否存在问题或故障,以排除硬件故障导致的性能问题。
查看内核日志:检查内核日志(通常位于/var/log/messages或/var/log/kern.log)以查找与性能问题相关的错误消息或警告。
使用性能剖析工具:使用如perf, gprof, valgrind等性能剖析工具来深入分析内核函数的执行时间。
检查调度策略:检查系统的调度策略(如CPU亲和性、优先级等)是否合理,并确保系统没有过度调度或饥饿现象。
请注意,分析内核执行时间过长的原因可能涉及复杂的调试过程,并且结果可能因系统配置和特定工作负载而异。在进行更改之前,建议备份重要数据并谨慎操作。

posted on 2023-07-05 11:20  ni_sy  阅读(10)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3