结构体初始化 kernel
时间: 2023-05-26 19:06:55 浏览: 53
在Kernel编程中,可以使用结构体来组织和管理数据,在定义结构体时,可以给结构体的成员变量赋初值来实现结构体的初始化。以下是一些初始化结构体的基本方法:
1. 使用花括号初始化
```c
typedef struct {
int x;
int y;
} Point;
Point p = {1, 2};
```
2. 按顺序初始化
```c
typedef struct {
int x;
int y;
} Point;
Point p = {1};
p.y = 2;
```
3. 指定成员变量初始化
```c
typedef struct {
int x;
int y;
} Point;
Point p = {.x = 1, .y = 2};
```
在Kernel中,建议使用第二种方法进行初始化,因为有些情况下,结构体的成员变量可能很多,使用花括号初始化方式会很冗长,不利于代码的可读性和维护性。
相关问题
linuxmodule结构体
Linux内核中,每个内核模块都对应一个结构体 linuxmodule,该结构体定义了内核模块的各种属性和函数指针,包括模块名、作者、许可证、初始化函数、清理函数等。下面是该结构体的定义:
```c
struct module {
enum module_state state; /* 模块状态 */
struct list_head list; /* 链接到内核的所有模块的链表 */
char name[MODULE_NAME_LEN]; /* 模块名 */
struct module_kobject mkobj; /* 模块kobject */
const char *version; /* 模块版本 */
const char *srcversion; /* 模块源码版本 */
struct kobject *holders_dir; /* 模块持有者的目录 */
struct kernel_symbol *syms; /* 模块导出符号的数组 */
unsigned int num_syms; /* 导出符号的数量 */
struct kernel_param *kp; /* 模块参数的数组 */
unsigned int num_kp; /* 模块参数的数量 */
unsigned int num_gpl_syms; /* 导出的GPL符号的数量 */
struct kernel_symbol *gpl_syms;/* 导出的GPL符号的数组 */
unsigned int num_unused_gpl_syms; /* 未使用的GPL符号的数量 */
struct kernel_symbol *unused_gpl_syms; /* 未使用的GPL符号的数组 */
const struct kernel_symbol *gpl_future_syms; /* 未定义的GPL符号 */
unsigned int num_gpl_future_syms; /* 未定义的GPL符号的数量 */
struct module_sect_attr *sect_attrs; /* 模块段属性的数组 */
struct module_notes_attrs *notes_attrs; /* 模块注释属性的数组 */
struct module_layout layout; /* 模块布局 */
const char *modinit_name; /* 模块初始化函数名 */
const char *modinfo_attrs; /* 模块信息属性 */
const char *args; /* 模块参数 */
void *percpu; /* 模块私有数据 */
unsigned int percpu_size; /* 模块私有数据的大小 */
struct module_init_freeing init; /* 模块初始化函数和清理函数 */
struct module_ref ref; /* 模块引用计数 */
const struct exception_table_entry *extable; /* 异常表 */
unsigned int num_exentries; /* 异常表项的数量 */
struct notifier_block *modinfo_notifier; /* 模块信息通知链 */
struct module_attribute *modinfo_attrs_ro; /* 只读模块信息属性 */
struct module_attribute *modinfo_attrs_rw; /* 可读写模块信息属性 */
u64 taints; /* 内核污点标志 */
const struct kernel_symbol *gpl_future_syms_ro; /* 只读未定义的GPL符号 */
unsigned int num_gpl_future_syms_ro; /* 只读未定义的GPL符号的数量 */
bool sig_ok:1; /* 是否允许使用非GPL符号 */
};
```
其中,比较重要的成员包括:
- state:模块状态,包括 MODULE_STATE_LIVE、MODULE_STATE_COMING、MODULE_STATE_GOING 等。
- name:模块名,长度不超过 MODULE_NAME_LEN。
- version:模块版本号。
- modinit_name:模块初始化函数名。
- init:包含模块初始化函数和清理函数指针的结构体。
- ref:模块引用计数的结构体。
- taints:内核污点标志,表示内核是否被修改过。
- sig_ok:是否允许使用非GPL符号。如果该成员为 false,表示该模块只能使用GPL符号,否则可以使用非GPL符号。
等待队列是在哪个阶段初始化的
等待队列(wait queue)是在内核初始化阶段被初始化的,具体来说,它是在内核启动过程中的初始化代码中被初始化的。在内核启动过程中,会调用由 init/main.c 文件中的 start_kernel() 函数启动的内核初始化过程。
在内核初始化过程中,等待队列是由宏定义 INIT_WAITQUEUE_HEAD(name) 在代码中定义和初始化的。例如,在某个模块中定义了一个等待队列 my_waitqueue,可以使用以下代码来对这个队列进行初始化:
```c
DECLARE_WAIT_QUEUE_HEAD(my_waitqueue);
```
这个宏定义会生成以下代码:
```c
wait_queue_head_t my_waitqueue = __WAIT_QUEUE_HEAD_INITIALIZER(my_waitqueue);
```
这个代码会定义一个名为 my_waitqueue 的等待队列,并初始化它的头部节点。等待队列的头部节点是一个 wait_queue_head_t 结构体,它包含了一个双向链表,用于存储等待这个事件的任务。在这个结构体中,我们可以使用宏定义 wait_event_*() 和 wake_up_*() 等函数来操作等待队列,具体的使用方法可以参考内核源代码中的相关注释。
总之,等待队列是在内核初始化阶段被初始化的,它由宏定义 INIT_WAITQUEUE_HEAD(name) 生成,并且可以使用 wait_event_*() 和 wake_up_*() 等函数来操作等待队列。