编译Linux内核源码的过程中发生的故事
目的
构建环境,学习 《Linux设备驱动程序》 《Linux内核设计与实现》
Linux环境
Fedora 24,内核版本4.5.5。
Linux 4.5.5-300.fc24.x86_64
下载内核源码
从https://www.kernel.org下载了4.19.128版本。
内核配置
使用make help
查看所有make选项。
可以使用不同的方法进行配置,比如make config
、make menuconfig
、make xconfig
等。
Liberators
归并排序
《算法(第4版)》笔记
归并
归并排序基于“归并”这个简单的操作,即将两个有序的数组归并成一个更大的有序数组。
要将一个数组排序,可以先(递归地)将它分成两半分别排序,然后将结果归并起来。
// c++
template<class T>
void merge(T& a, int lo, int mid, int hi, T& aux)
{
// 将a[lo .. mid]和a[mid+1 .. hi]归并
int i = lo;
int j = mid + 1;
for (int k=lo; k<=hi; ++k)
aux[k] = a[k];
for (int k=lo; k<=hi; ++k)
{
if (i > mid)
a[k] = aux[j++];
else if (j > hi)
a[k] = aux[i++];
else if (aux[j] < aux[i])
a[k] = aux[j++];
else
a[k] = aux[i++];
}
}
初级排序算法
《算法(第4版)》笔记
选择排序
首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法叫做选择排序,因为它在不断地选择剩余元素之中的最小者。
选择排序的缺点:一个已经有序的数组或是主键全部相等的数组和一个元素随机排列的数组所用的排序时间竟然一样长。
// c++
// 将容器a按升序排列
template<class T>
void selection_sort(T& a)
{
int n = a.size();
for (int i=0; i<n; ++i)
{
int min = i;
for (int j=i+1; j<n; ++j)
{
if (a[j] < a[min])
min = j;
}
std::swap(a[i], a[min]);
}
}
不要推倒重来
摘自《Python基础教程》
虽然这里提倡使用原型,但务必对推倒重来持谨慎态度,在你为编写原型投入了不少时间和精力时尤其如此。更好的选择可能是,对原型进行重构和修改,让其变成功能上更好的系统,其原因有多个。
一个可能出现的常见问题是“第二系统综合征”,即力图让第二个版本非常灵巧或完美无缺,导致永远没有完工的时候。
“不断重写综合征”在小说创作领域很常见,指的是不断地修改程序,甚至推倒重来。在有些情况下,让程序“还行”可能是最佳的策略——管用就好。
还有“代码疲劳症”,即你对代码逐渐感到厌烦。你花了很长时间来编写代码,却发现它丑陋而笨拙。导致代码看起来粗糙而笨拙的原因之一是,必须处理各种特殊情况并包含多种形式的错误处理等。无论如何,在新版本中也必须包含这些功能,而最初为了实现它们,你可能花了很大的精力(更别说为调试花费的精力了)。
换而言之,如果你觉得原型还有得救,能变成可行的系统,就应竭尽所能地修改它,而不是推倒重来。在本书后面关于开发项目的章节中,我将开发成果分成了界线清晰的两个版本:原型和最终程序。这样做既是出于清晰考虑,也是为了突出通过编写软件的第一个版本获得的经验和洞察力。在实际开发工作中,完全可以先开发原型,再通过重构它来获得最终的系统。
要深入地了解推倒重来的恐怖之处,请参阅Joel Spolsky撰写的文章“Things You Should Never Do, Part I”(joelonsoftware.com)。据Spolsky讲,对所有软件公司来说,推倒重来都是最严重的策略性错误。
换了新的博客系统
SDL2 笔记
《SDL Game Development》笔记
坐标系
原点:左上角
SDL扩展
SDL_image
支持多种格式图片加载:BMP GIF PNG TGA PCX ...
SDL_net
跨平台网络库
SDL_mixer
audio mixer library. 支持MP3 MIDI OGG
SDL_ttf
支持TrueType字体
SDL_rtf
support the rendering of the Rich Text Format (RTF).
SDL_Init()
初始化标识
SDL_INIT_HAPTIC Force feedback subsystem 力反馈
SDL_INIT_AUDIO Audio subsystem
SDL_INIT_VIDEO Video subsystem
SDL_INIT_TIMER Timer subsystem
SDL_INIT_JOYSTICK Joystick subsystem
SDL_INIT_EVERYTHING All subsystems
SDL_INIT_noparachute Don't catch fatal signals
查看一个子系统是否已被初始化:
if (SDL_WasInit(SDL_INIT_VIDEO) != 0)
cout << "video was initialized";
SDL_CreateRenderer()
SDL_RENDERER_SOFTWARE Use software rendering
SDL_RENDERER_ACCELERATED Use hardware acceleration
SDL_RENDERER_PRESENTVSYNC Synchronize renderer update with screen's refresh rate
SDL_RENDERER_TARGETTEXTURE Supports render to texture
游戏程序结构
初始化
游戏循环:获取输入 物理运算 渲染
退出
window flags
SDL_WINDOW_FULLSCREEN Make the window fullscreen
SDL_WINDOW_OPENGL Window can be used with as an OpenGL context
SDL_WINDOW_SHOWN The window is visible
SDL_WINDOW_HIDDEN Hide the window
SDL_WINDOW_BORDERLESS No border on the window
SDL_WINDOW_RESIZABLE Enable resizing of the window
SDL_WINDOW_MINIMIZED Minimize the window
SDL_WINDOW_MAXIMIZED Maximize the window
SDL_WINDOW_INPUT_GRABBED Window has grabbed input focus
SDL_WINDOW_INPUT_FOCUS Window has input focus
SDL_WINDOW_MOUSE_FOCUS Window has mouse focus
SDL_WINDOW_FOREIGN The window was not created using SDL
程序基本结构
#include <SDL.h>
SDL_Window* g_pWindow = 0;
SDL_Renderer* g_pRenderer = 0;
int main(int argc, char* argv[])
{
// initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING) >= 0)
{
// if succeeded create our window
g_pWindow = SDL_CreateWindow("Chapter 1: Setting up SDL",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480,
SDL_WINDOW_SHOWN);
// if the window creation succeeded create our renderer
if (g_pWindow != 0)
{
g_pRenderer = SDL_CreateRenderer(g_pWindow, -1, 0);
}
}
else
return 1; // sdl could not initialize
// everything succeeded lets draw the window
bool bQuit = false;
while (true)
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
bQuit = true;
break;
}
}
if (bQuit)
break;
// set to black
// This function expects Red, Green, Blue and Alpha as color values
SDL_SetRenderDrawColor(g_pRenderer, 0, 0, 0, 255);
// clear the window to black
SDL_RenderClear(g_pRenderer);
// show the window
SDL_RenderPresent(g_pRenderer);
}
// set a delay before quitting
//SDL_Delay(5000);
// clean up SDL
SDL_Quit();
return 0;
}
绘制图片过程
- 加载图片获得SDL_Surface
- 根据Surface获得SDL_Texture
- 获得纹理尺寸:SDL_QueryTexture
- 渲染:SDL_RenderCopy/SDL_RenderCopyEx 需要Renderer参数
SDL使用两种数据结构渲染到屏幕
SDL_Surface 像素集 使用软件渲染(not GPU)
SDL_Texture 使用硬件加速
SDL_Texture* m_pTexture
SDL_Rect m_sourceRectangle;
SDL_Rect m_destinationRectangle;
// 根据图片创建SDL_Texture
SDL_Surface* pTempSurface = SDL_LoadBMP("asserts/rider.bmp");
m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
SDL_FreeSurface(pTempSurface);
// 获得图片的大小
SDL_QueryTexture(m_pTexture, NULL, NULL,
&m_sourceRectangle.w, &m_sourceRectangle.h);
SDL_RenderClear();
SDL_RenderCopy(m_pRenderer, m_pTexture,
&m_sourceRectangle, &m_destinationRectangle);
SDL_RenderPresent();
源矩形 目标矩形 参数传入0 将整个纹理渲染到整个窗口。
SDL_GetTicks() 毫秒
SDL_RenderCopyEx() 支持旋转和翻转Flip
SDL_image
sdl2_image.lib
#include <sdl_image.h>
SDL_Surface* pTempSurface = IMG_Load("animate.png");
Fixed frames per second (FPS) is
not necessarily always a good option, especially when your game includes more
advanced physics. It is worth bearing this in mind when you move on from this
book and start developing your own games. Fixed FPS will, however, be fine for
the small 2D games, which we will work towards in this book.
固定帧频
const int FPS = 60;
const int DELAY_TIME = 1000.0f / FPS; // 1000毫秒
while (...)
{
frameStart = SDL_GetTicks(); // 毫秒
...
frameTime = SDL_GetTicks() - frameStart;
if (frameTime < DELAY_TIME)
SDL_Delay((int)(DELAY_TIME - frameTime));
}
SDL joystick event
SDL_JoyAxisEvent Axis motion information
SDL_JoyButtonEvent Button press and release information
SDL_JoyBallEvent Trackball event motion information
SDL_JoyHatEvent Joystick hat position change
SDL joystick event Type value
SDL_JoyAxisEvent SDL_JOYAXISMOTION
SDL_JoyButtonEvent SDL_JOYBUTTONDOWN or
SDL_JOYBUTTONUP
SDL_JoyBallEvent SDL_JOYBALLMOTION
SDL_JoyHatEvent SDL_JOYHATMOTION
不同的游戏控制器 按钮和轴可能有不同的值 比如Xbox360 controller, PS3 controller
Xbox360 controller:
Two analog sticks
Analog sticks press as buttons
Start and Select buttons
Four face buttons: A, B, X, and Y
Four triggers: two digital and two analog
A digital directional pad
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
if (SDL_NumJoysticks() > 0)
{
for (int i=0; i<SDL_NumJoysticks(); ++i)
{
SDL_Joystick* joy = SDL_JoystickOpen(i);
if (SDL_JoystickOpened(i) == 1)
m_joysticks.push_back(joy);
}
SDL_JoystickEventState(SDL_ENABLE);
}
SDL_JoystickClose(joy);
分辨是哪个控制器的事件
if (event.type == SDL_JOYAXISMOTION)
int whichOne = event.jaxis.which;
控制器按钮
SDL_JoystickNumButtons
event.jbutton.button // 按钮ID
鼠标事件
SDL Mouse Event Purpose
SDL_MouseButtonEvent A button on the mouse has been pressed or released
SDL_MouseMotionEvent The mouse has been moved
SDL_MouseWheelEvent The mouse wheel has moved
SDL Mouse Event Type Value
SDL_MouseButtonEvent SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP
SDL_MouseMotionEvent SDL_MOUSEMOTION
SDL_MouseWheelEvent SDL_MOUSEWHEEL
// 鼠标按钮
// SDL numbers these as 0 for left, 1 for middle, and 2 for right.
if (event.type == SDL_MOUSEBUTTONDOWN)
if (event.button.button == SDL_BUTTON_LEFT)
event.type SDL_MOUSEMOTION
event.motion.x
event.motion.y
// 键盘
1 表示按下 0 表示没有按下
SDL_GetKeyboardState(int* numkeys)
Uint8* m_keystates;
m_keystates = SDL_GetKeyboardState(0);
SDL_Scancode key;
if (m_keysttes[key] == 1)
有限状态机
需要能够处理以下情况:
Removing one state and adding another
Adding one state without removing the previous state
Removing one state without adding another
Game
GameObject
TextureManager // 负责加载图片文件,负责绘制,纹理ID
InputHandler
GameState
GameStateMachine
GameObjectFactory
StateParser
Distributed Factory
class GameObjectFactory
std::map<std::string, BaseCreator*> m_creators;
registerType(std::string typeID, BaseCreator* pCreator);
https://github.com/ReneNyffenegger/development_misc/tree/master/base64.
The base64.h and base64.cpp files can be added directly to the project.
SDL_Mixer
Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize)
Mix_OpenAudio(22050, AUDIO_S16, 2, 4096);
std::map<std::string, Mix_Chunk*> mSfxs;
std::map<std::string, Mix_Chunk*> mMusic;
Mix_Music* music = Mix_LoadMUS(filename); // ogg
Mix_Chunk* chunk = Mix_LoadWAV(filename); // wav
Mix_PlayMusic() // Mix_Music
Mix_PlayChannel() // Mix_Chunk
Mix_CloseAudio();
SDL_SetTextureAlphaMod()
SDL 笔记
开发环境配置
http://tjumyk.github.io/sdl-tutorial-cn/contents.html
VS 新建项目选择控制台程序,链接属性中选择子系统“/SUBSYSTEM:WINDOWS”。
在屏幕上显示一张图片
#include <SDL/SDL.h>
int main(int argc, char *args[])
{
SDL_Surface *hello = nullptr;
SDL_Surface *screen = nullptr;
SDL_Init(SDL_INIT_EVERYTHING);
// 设置窗口
screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
// 加载图像
hello = SDL_LoadBMP("hello.bmp");
// 将图像应用到窗口上
SDL_BlitSurface(hello, nullptr, screen, nullptr);
// 更新窗口
SDL_Flip(screen);
SDL_Delay(2000);
// 释放资源
SDL_FreeSurface(hello);
SDL_Quit();
return 0;
}
敏捷软件开发,可持续的开发速度
以下摘自《敏捷软件开发:原则、模式与实践》。
可持续的开发速度:
软件项目不是全速短跑,它是马拉松长跑。那些一跃过起跑线就开始尽力狂奔的团队将会在远离终点前就筋疲力尽。为了快速地完成开发,团队必须要以一种可持续的速度前进。团队必须保持旺盛的精力和敏锐的警觉。团队必须要有意识地保持稳定、适中的速度。
XP(极限编程)的规则不允许团队加班工作。在版本发布前的一个星期是该规则的唯一例外。如果发布目标就在眼前并且能够一蹴而就,则允许加班。