当前位置: 首页 > news >正文

Linux内核C语言代码规范

Linux内核C语言代码规范

一、命名规范详解

1. 变量/函数命名
/* 正确示例 */
int device_driver_count;        // 设备驱动计数
void register_pci_device(void); // 注册PCI设备/* 错误示例 */
int DeviceCount;                // 首字母大写
void RegisterPCI();             // 首字母大写+缩写

规范要求

  • 全小写snake_case,单词间用下划线连接
  • 全局变量/函数需带模块前缀(如pci_, usb_
  • 避免缩写(除非广泛接受如dev
2. 类型定义
/* 正确示例 */
struct list_head {      // 链表头struct list_head *next, *prev;
};
typedef void (*irq_handler_t)(int, void*);  // 中断处理函数指针/* 错误示例 */
typedef struct {        // 匿名结构体int x, y;
} Point_t;              // _t后缀用于基本类型

规范要求

  • 结构体/联合体使用struct关键字显式声明
  • typedef仅用于函数指针和特定场景
  • 避免使用_t后缀(内核约定)
3. 宏命名
/* 正确示例 */
#define MAX_IRQ_NUM 256                 // 常量宏
#define container_of(ptr, type, member) // 函数式宏((type *)((char *)(ptr) - offsetof(type, member)))/* 错误示例 */
#define MaxIrq 256      // 混合大小写
#define min(a,b) a<b?a:b // 缺少参数括号

规范要求

  • 常量宏全大写SCREAMING_SNAKE_CASE
  • 函数式宏使用小写和括号保护参数
  • 多行宏用do {...} while(0)包裹

二、格式规范详解

1. 缩进与空格
/* 正确示例 */
if (irq < MAX_IRQ_NUM) {    // 关键字后空格struct irq_desc *desc = &irq_desc[irq];  // *靠近变量名desc->handler(irq, desc->dev_id);        // ->操作符无空格
}/* 错误示例 */
if(irq<MAX_IRQ_NUM){        // 缺少空格struct irq_desc* desc = &irq_desc [ irq ]; // *位置错误+多余空格
}

规范要求

  • 8字符Tab缩进(非空格)
  • 关键字后加空格:if (, while (
  • 指针声明:char *ptr*靠左)
  • 操作符两侧空格:a = b + c
2. 大括号规则
/* 函数 */
int init_module(void)        // 函数大括号独占一行
{/* ... */
}/* 语句块 */
if (condition) {             // 左大括号同行do_this();do_that();
} else {                     // else单独一行do_otherwise();
}/* 单行语句 */
if (condition)single_statement();      // 无大括号但独占一行
3. 行长度与换行
/* 正确换行 */
static int process_packet(struct sk_buff *skb, struct net_device *dev,struct packet_type *pt)
{return netif_rx(skb) == NET_RX_SUCCESS ? 0 : -EIO;
}/* 错误换行 */
int result = function_with_long_name(argument1, argument2, argument3, argument4);  // 错误:续行缩进不足

规范要求

  • 行长度≤100字符
  • 续行对齐参数或操作符
  • 函数参数过多时每行一个参数

三、文件组织规范

1. 头文件格式
#ifndef _LINUX_SCHED_H     // 保护宏格式:_LINUX_<文件名>_H
#define _LINUX_SCHED_H#include <linux/pid.h>     // 标准头文件
#include <asm/current.h>   // 体系结构相关头文件/* 内联函数 */
static inline void __set_task_state(struct task_struct *tsk, int state)
{tsk->state = state;
}/* 函数声明 */
extern void scheduler_tick(void);#endif /* _LINUX_SCHED_H */
2. 源文件结构
/* * 文件注释:描述模块功能* Copyright (c) ... 许可证信息*/
#include <linux/module.h>
#include "internal.h"       // 本地头文件#define LOCAL_DEBUG 0       // 本地宏定义static int instance_count;  // 静态全局变量/* 主功能函数 */
int core_function(void)
{/* ... */
}/* 辅助函数 */
static void helper(void)    // 静态函数
{/* ... */
}

四、内核特有规范

1. 错误处理模式
int device_probe(struct device *dev)
{int ret;struct resource *res;res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);if (!res)return -ENOMEM;     // 直接返回错误码ret = device_init(res);if (ret < 0)goto err_init;      // 错误时跳转清理ret = register_device(res);if (ret < 0)goto err_register;return 0;/* 逆向资源释放 */
err_register:device_deinit(res);
err_init:devm_kfree(dev, res);return ret;
}
2. 并发控制
static DEFINE_SPINLOCK(counter_lock);
static atomic_t online_devices = ATOMIC_INIT(0);void add_device(void)
{unsigned long flags;spin_lock_irqsave(&counter_lock, flags); // 保存中断状态atomic_inc(&online_devices);spin_unlock_irqrestore(&counter_lock, flags);
}
3. 内存管理
/* 标准分配 */
struct data *p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)return -ENOMEM;/* 清零分配 */
struct config *cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);/* 高性能对象池 */
static struct kmem_cache *data_cache;data_cache = kmem_cache_create("data_cache", sizeof(struct data), 0, SLAB_HWCACHE_ALIGN, NULL);
struct data *item = kmem_cache_alloc(data_cache, GFP_KERNEL);

五、注释规范

1. 函数注释
/*** irq_handler - 中断服务函数* @irq: 中断号* @dev_id: 设备标识指针** 处理来自设备的硬件中断,读取状态寄存器并* 调度下半部处理程序。** 返回: IRQ_HANDLED 表示成功处理*/
irqreturn_t irq_handler(int irq, void *dev_id)
{/* ... */return IRQ_HANDLED;
}
2. 数据结构注释
/** 进程描述符 - 内核中进程/线程的核心数据结构* * @state: 进程状态(运行、睡眠等)* @stack: 内核栈指针* @tasks: 用于链接到任务列表*/
struct task_struct {volatile long state;void *stack;struct list_head tasks;/* ... */
};

六、典型违规案例

案例1:命名不规范
// 错误
int DeviceCounter;              // 首字母大写
#define MAXDEV 10               // 未全大写// 正确
int device_count;
#define MAX_DEVICES 10
案例2:指针声明位置错误
// 错误
char* buffer;                   // *靠近类型// 正确
char *buffer;                   // *靠近变量名
案例3:大括号使用错误
// 错误
if (condition)
{do_something();             // 左大括号单独一行
}// 正确
if (condition) {do_something();
}

七、工具使用示例

1. checkpatch.pl检查
$ ./scripts/checkpatch.pl -f --strict drivers/net/ethernet.c
2. 代码格式化
$ ./scripts/Lindent drivers/char/mydriver.c
3. 静态分析
$ make C=2 drivers/usb/

总结:Linux内核编码黄金法则

  1. 可读性优先:代码是给人看的,其次才是机器
  2. 一致性至上:严格遵循现有代码风格
  3. 内存安全:每次分配都要考虑释放路径
  4. 并发意识:假设代码会在多核环境运行
  5. 性能敏感:关键路径避免函数调用和分支

内核大师Linus Torvalds的忠告:“糟糕的代码不会被接受,无论它实现了多么炫酷的功能。良好的风格是进入内核社区的门票。”

通过严格遵守这些规范,开发者可以:

  • 提高代码被主线接纳的概率
  • 减少内存泄漏和竞态条件风险
  • 增强代码可维护性和可读性
  • 加速代码审查过程
  • 建立良好的内核开发声誉
http://www.lryc.cn/news/610826.html

相关文章:

  • MySQL内外连接详解
  • Python 基础语法(二):流程控制语句详解
  • 【Qt开发】常用控件(一)
  • 嵌入式硬件中运放的基本控制原理
  • 选佳沐信,智享便捷,乐在其中
  • LeetCode——2683. 相邻值的按位异或
  • 下架的软件又复活了,低调使用!
  • HFSS许可审计与分析
  • 用 Python 批量处理 Excel:从重复值清洗到数据可视化
  • Go语言实战案例:使用context控制协程取消
  • 【工程化】tree-shaking 的作用以及配置
  • 小杰数据结构——题库——拂衣便欲沧海去,但许明月随吾身
  • EP02:【DL 第二弹】张量的索引、分片、合并以及维度调整
  • WWDC 25 极地冰原撸码危机:InlineArray 与 Span 的绝地反击
  • 基于MCP的智能客服系统:知识库与工单系统深度集成
  • C++ 网络编程入门:TCP 协议下的简易计算器项目
  • 面向对象编程基础:类的实例化与对象内存模型详解
  • 什么是mysql的垂直分表,理论依据是什么,如何使用?
  • 单链表应用实践
  • 【PCIE044】基于 JFM7VX690T 的全国产化 FPGA 开发套件
  • FPGA 基本设计思想--乒乓操作、串并转换、流水线
  • 数学建模算法-day[15]
  • 【MATLAB】(八)矩阵
  • 技术与情感交织的一生 (十一)
  • HTTP 与 HTTPS 的区别深度解析:从原理到实践
  • kettle插件-kettle http post plus插件,轻松解决https post接口无法调用文件流下载问题
  • 攻击实验(ARP欺骗、MAC攻击、报文洪水攻击、DNS欺骗)
  • 在 MCP 中实现 “askhuman” 式交互:原理、实践与开源方案
  • 灰色优选模型及算法MATLAB代码
  • 信息安全概述--实验总结