唯客微博客

专注于计算机,嵌入式领域的技术

0%

Kconfig-language翻译

1. 介绍

配置数据库是按树结构组织的配置选项的集合:

1
2
3
4
5
6
7
8
9
10
11
12
+- Code maturity level options
| +- Prompt for development and/or incomplete code/drivers
+- General setup
| +- Networking support
| +- System V IPC
| +- BSD Process Accounting
| +- Sysctl support
+- Loadable module support
| +- Enable loadable module support
| +- Set version information on all module symbols
| +- Kernel module loader
+- ...

每个条目都有自己的依赖性。 这些依赖关系用于确定条目的可见性。 任何子条目只有在其父条目也可见的情况下才可见。

阅读全文 »

操作系统精髓与设计原理(第8版) - 第二章 操作系统概述

2.1 操作系统的目标与功能

操作系统是控制应用程序执行的程序,是应用程序和计算机硬件间的接口。它有三个目标:

  • 方便:操作系统使计算机更易于使用。
  • 有效:操作系统允许以更有效的方式使用计算机系统资源。
  • 扩展能力:在构造操作系统时,应允许在不妨碍服务的前提下,有效地开发、测试和引入新的系统功能。

2.1.1 作为用户/计算机接口的操作系统

阅读全文 »

操作系统精髓与设计原理(第8版) - 第一章 计算机系统概述

1.1 基本构成

计算机由处理器、存储器和输入/输出部件组成,每类部件都有一个或多个模块。主要是4个结构化部件:

处理器:控制计算机的操作,执行数据处理功能。

内存:存储数据和程序。

阅读全文 »

Linux驱动开发杂记(0x1B) - 内核链表数据结构的实现

1. Linux内核双链表

链表的基础知识在这里就不在赘述了。Linux 内核提供了一种双链表的实现方式,实际上,通常它都组织成双循环链表。

链表数据结构的定义很简单,在Linux 4.15.0 中,list_head结构体定义在include/linux/types.h文件中。

1
2
3
struct list_head {
struct list_head *next, *prev;
};
阅读全文 »

Linux驱动开发杂记(0x1A) - 内核中的原子操作

具体的接口API函数整理如下:

接口函数 描述
atomic_inc 原子变量的值加一
atomic_inc_return 同上,只不过将变量v的最新值返回
atomic_inc_and_test 递增v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假
atomic_dec 原子变量的值减去一
atomic_dec_return 同上,只不过将变量v的最新值返回
atomic_dec_and_test 递减v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假
atomic_add 给一个原子变量v增加i
atomic_sub 给一个原子变量v减去i
atomic_sub_and_test 给一个原子变量v减去i,并判断变量v的最新值是否等于0
atomic_add_negative 将v指向的原子变量加上i,并测试结果是否为负。若为负,返回真,否则返回假
atomic_read 读取v指向的原子变量的值
atomic_set 设置v指向的原子变量的值为i
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

// 原子变量的值加一
static inline void atomic_inc(atomic_t *v)
{
atomic_add_return(1, v);
}
// 同上,只不过将变量v的最新值返回
#define atomic_inc_return(v) atomic_add_return(1, (v))
// 递增v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假
#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)

// 原子变量的值减去一
static inline void atomic_dec(atomic_t *v)
{
atomic_sub_return(1, v);
}
// 同上,只不过将变量v的最新值返回
#define atomic_dec_return(v) atomic_sub_return(1, (v))
// 递减v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假
#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)


// 给一个原子变量v增加i
static inline void atomic_add(int i, atomic_t *v)
{
atomic_add_return(i, v);
}

// 给一个原子变量v减去i
static inline void atomic_sub(int i, atomic_t *v)
{
atomic_sub_return(i, v);
}
// 给一个原子变量v减去i,并判断变量v的最新值是否等于0
#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)


// 将v指向的原子变量加上i,并测试结果是否为负。若为负,返回真,否则返回假
static inline int atomic_add_negative(int i, atomic_t *v)
{
return atomic_add_return(i, v) < 0;
}

// 读取v指向的原子变量的值
#define atomic_read(v) READ_ONCE((v)->counter)
// 设置v指向的原子变量的值为i
#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))

Linux驱动开发杂记(0x18) - 内核tty接口各版本的变化(二)之tty_driver.h

2.6.17 - 2.6.18

删除

1
2
3
struct tty_driver {
const char *devfs_name;
}
## 2.6.19 - 2.6.20 修改
1
2
3
4
5
struct tty_operations {
void (*set_termios)(struct tty_struct *tty, struct termios * old);
//改为
void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
}
阅读全文 »

Linux驱动开发杂记(0x17) - 内核tty接口各版本的变化(一)之tty_flip.h

2.6.15 - 2.6.16

添加

1
2
3
4
5
extern int tty_buffer_request_room(struct tty_struct *tty, size_t size);
extern int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size);
extern int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size);
extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
修改
1
2
3
_INLINE_ void tty_insert_flip_char(struct tty_struct *tty, unsigned char ch, char flag)
//改为
_INLINE_ int tty_insert_flip_char(struct tty_struct *tty, unsigned char ch, char flag)
阅读全文 »

2.6.13 - 2.6.14

添加

1
#define DEFINE_TIMER(_name, _function, _expires, _data)
## 2.6.14 - 2.6.15 添加
1
2
3
4
static inline void setup_timer(struct timer_list * timer,
void (*function)(unsigned long),
unsigned long data)

## 3.6 - 3.7
1
2
3
4
5
6
7
void init_timer_key(struct timer_list *timer,
const char *name,
struct lock_class_key *key);
// 改为
void init_timer_key(struct timer_list *timer, unsigned int flags,
const char *name, struct lock_class_key *key);

阅读全文 »

  为了提高系统的响应能力和并发能力,Linux将中断处理分了上半部和下半部。当一个中断产生,调用该中断对应的处理程序(上半部),然后告诉系统,对应的后半部可以执行了,中断处理程序立即返回,下半部会在合适的时机由操作系统调用。这样一来就大大的减少了中断处理所需要的时间。

tasklet是中断处理下半部分最常用的一种方法,驱动程序一般先申请中断,在中断处理函数内完成中断上半部分的工作后调用tasklet。

一、tasklet的特点

  1. tasklet只可以在一个CPU上同步地执行,不同的tasklet可以在不同地CPU上同步地执行。
  2. tasklet的实现是建立在两个软件中断的基础之上的,即HI_SOFTIRQ和TASKLET_SOFTIRQ,本质上没有什么区别,只不过HI_SOFTIRQ的优先级更高一些
  3. 由于tasklet是在软中断上实现的,所以像软中断一样不能睡眠、不能阻塞,处理函数内不能含有导致睡眠的动作,如减少信号量、从用户空间拷贝数据或手工分配内存等。
  4. 一个 tasklet 能够被禁止并且之后被重新使能; 它不会执行直到它被使能的次数与被禁止的次数相同.
  5. tasklet的串行化使tasklet函数不必是可重入的,因此简化了设备驱动程序开发者的工作。
  6. 每个cpu拥有一个tasklet_vec链表,具体是哪个cpu的tasklet_vec链表,是根据当前线程是运行在哪个cpu来决定的。

二、tasklet结构体

阅读全文 »