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

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.xdnf.cn/news/17246.html

相关文章:

  • LangGraph学习笔记 — LangGraph中State状态模式
  • 数据安全治理——解读数据安全治理与评估服务业务介绍【附全文阅读】
  • oelove奥壹新版v11.7旗舰版婚恋系统微信原生小程序源码上架容易遇到的几个坑,避免遗漏参数白屏显示等问题
  • 相机拍摄的DNG格式照片日期如何修改?你可以用这款工具修改
  • vue3 子组件和子组件的通讯 mitt
  • 分布式选举算法:Bully、Raft、ZAB
  • 私有云盘新体验:FileRise在cpolar的加持下如何让数据管理更自由?
  • golang实现支持100万个并发连接(例如,HTTP长连接或WebSocket连接)系统架构设计详解
  • 第13届蓝桥杯Scratch_选拔赛_真题2021年11月27日
  • Guava 与 Caffeine 本地缓存系统详解
  • 2048小游戏
  • 【java】大数据insert的几种技术方案和优缺点
  • (ZipList入门笔记一)ZipList的节点介绍
  • Windows 电脑远程访问,ZeroTier 实现内网穿透完整指南(含原理讲解)
  • Spring Boot 整合 Web 开发全攻略
  • 深度拆解Dify:开源LLM开发平台的架构密码与技术突围
  • 消息队列疑难问题(RocketMQ)
  • 09-堆
  • GaussDB 常见问题-集中式
  • 8.5 CSS3多列布局
  • lumerical——Y分支功分器
  • Redis Stream:高性能消息队列核心原理揭秘
  • PDF转图片工具技术文档(命令行版本)
  • CRT调试堆检测:从原理到实战的资源泄漏排查指南
  • 北京JAVA基础面试30天打卡02
  • RocketMq如何保证消息的顺序性
  • 面向对象的七大设计原则
  • Kotlin属性委托
  • 探秘MOBILITY China 2026,新能源汽车与智慧出行的未来盛宴
  • React18 严格模式下的双重渲染之谜