wpe7.jpg (11495 bytes)

我的征尘是星辰大海。。。

The dirt and dust from my pilgrimage forms oceans of stars...

-------当记忆的篇章变得零碎,当追忆的图片变得模糊,我们只能求助于数字存储的永恒的回忆

作者:黄教授

二〇一六


一月一日当前只有等待等待

心里有一个念头就是想要完整的理解在一个程序的main发生以前的故事,从哪里入手呢?LSB的接口定义肯定是一个线索,然后闲逛到了object file的.eh_frame的section的部分,我对于这个部分有触目惊心的感受,所以格外留意了一下,这里提到了dwarf的格式,原来的链接已经失效,dwarf现在有了官方网站,下载了3.0的标准

一月二日当前只有等待等待

抓取dvd和transcoding是截然两个方面,libdvdcss解决了加密的问题,libdvdread是它的包装让读取透明,对于 libdvdnav本来是前者的一部分,也是解决了dvd的类似文件化读取的作用,对于我需要的subtitle没有帮助。难道如同h264一样是 stream中的一部分?handbrake是直接使用x264,这一点和ffmpeg一样的,所以,我想这个问题要用libx264来解决。以下部分是 我抓取字幕burn在video的办法。
HandBrakeCLI -i /dev/sr0 -o YesPrimeMinister16.m4v -Z "High Profile" -s 1 --subtitle-burned 1 --subtitle-default 1 -t 6

一月五日当前只有等待等待

nfs的隐含文件无法删除?首先使用lsof查看那个进程在使用。

一月九日当前只有等待等待

究竟为什么需要factory pattern呢?从前我是似是而非的明白,其实最关键的因素是我们不知道怎样dynamic load class。其实,这才是问题的要害。这里是一些很好的关于library的阅读材料。本来我以为我已经知道这篇文章的每一个字的意思,发现我还是有不知道的地方,能这样替代LD_LIBRARY_PATH: /lib/ld-linux.so.2 --library-path PATH EXECUTABLE

一月十四日当前只有等待等待

相当复杂的问题。说来话长,从何说起呢?这个是openssl需要线程保护的机制。 到底谁来设定也许不重要,问题是两个或以上的程序都想来设定,那就有问题了。尤其是在一方已经设定正在运行中另一个莽撞的家伙把这个callback改变 称自己的就有可能导致线程同步失败。我们使用了一个无代码支持的动态库,现在已知它使用了openssl的回调,(怎么知道的?原本就是一家公司,透过渠 道辗转闻到的,同时我使用link debug看到它有绑定函数。strace看不到的,因为不是系统syscall)但是不知道它是否是一个负责任的程序,比如我使用的gsoap也需要设 定,我的代码已经改为在set前调用get回调看是否有人设定了,但是日本人的代码写的太早了程序员没有意识这个会有被多个程序共同调用openssl的 问题,因此就是简单设定。其中的插曲是一个细节迷惑了我一个晚上睡不好觉,我们使用这个动态库的代码比较诡异,大概是有些全局变量或者static的变量 直接初始化用到动态库的函数或者什么导致在我的应用程序在main函数之前就被它设定了openssl的回调以至于我开始怀疑是不是我的理论错了,不然我 没有初始化调用动态库前居然它或者谁就设定了回调,难道openssl新版本提供默认实现回调?后来自己亲自调用openssl的实验代码证明这个一定要 使用者设定初始值一定是null,请看一下:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
int main(void)
{
                OPENSSL_init();
                typedef void (*FuncType) (int ,int ,const char *, int );
                FuncType callback= NULL;
                callback = CRYPTO_get_locking_callback();
                printf("callback=%p\n", callback);
                return 0;
}

这个经过编译链接无论什么版本的openssl都是输出NULL而不是我们的动态库事先已经被设定了。这个问题复杂就在于总共有三个模块都需要设定 这个回调,最好的结果是把这个工作交给应用模块去作,因为它最先运行,可是矛盾的是我们使用的是动态加载所以是最糟糕的情况,因为如果是动态链接反而好了 因为日本的库在运行main之前就已经设定了,反而相安无事,糟糕的是动态加载发生在web server已经设定了突然被它改变导致这个过程中可能发生线程安全是被。而且我们没有其源代码也没有接口控制它的行为。

测试这个代码的时候还有一些有趣的问题,openssl目前只能用gcc来编译,我们的代码是g++编译的,我要把这样的测试代码嵌入到程序里打印输出就只能这样子:
extern "C" {
#include <openssl/crypto.h>
#include <openssl/ssl.h>
void debug(){
typedef void (*FuncType) (int ,int ,const char *, int );
                FuncType callback= NULL;
                callback = CRYPTO_get_locking_callback();
                printf("callback=%p\n", callback);
}
} // extern "C"

前两个星期的问题其实更复杂一些,牵涉到动态库链接的问题,我们需要维持兼容性就把不同版本的动态库放在同一目录下通过动态加载达到控制api版本 输出的效果,问题在于linux的ld.so.x默认使用的是lazy模式也就是说动态库不会立刻resolve任何的symbol按照我读到的文章说, linker loader很聪明的在所有要resolve的symbol,(通常是函数,因为变量是要立刻resolve的没有lazy)大概是PLT (procedurel lookup table)的那些0x00000000改写成linker的resolve的函数地址,那样子当这个函数在第一次被执行的时候就实现了resolve, 当然这个函数是在找到真正的函数地址后写回PLT再去调用一次这个地址,这就是聪明的lazy的实现,非常的聪明。但是这个聪明导致了我们的设计失败:

MS===>(MF1, MF2)

MF1===>(HF1, HC1)

HF1===>(HC1)

MF2===>(HF2,HC2)

HF2===>(HC2)
MS是一个server需要动态加载两个几乎一样的不同版本的动态库MF1,MF2,其中的symbol即函数无论名字参数几乎一样,而MF1,MF2又 各自动态连接了两个不同版本的几乎相同的动态库HF1,HF2,以及他们各自的附属动态库HC1,HC2。这一切的目的是想要动态实现两个版本的程序同时 运行,MF1,HF1,HC1是一个版本,MF2,HF2,HC2是另一个版本,等于是在第一代程序升级后的版本,其中肯定很多函数代码接口没有太大的改 变。本来依照动态库链接使用SONAME的办法在linux下两个不同版本的动态库是可以共存在一个目录下的只要在编译期进行了正确的链接,这个都不是问 题。但是在运行期的莫名的近似于随机的crash让人感到困惑,后来设定LD_DEBUG环境变量发现同样的symbol在HC1中第一次被 resolve后不再在HC2中去resolve,这个当然是可以理解的:如果symbol是global的那么对于签名完全一致的symbol第一次 load起来的HC1的symbol成为了GOT的一部分,那么以后的lazy模式在设定resolve函数指针之前就已经要先搜寻GOT然后才lazy 的改写PLT的地址为resolve的函数地址,也就是说压根儿就已经resolve了不用lazy模式了。所以,ldopen的模式需要 private,但是对于lazy的模式我还是心存忧虑,于是另外两个flag也被我加上了now和deep-binding,now是要loader立 刻把所有的symbol都resolve,但是我实验过一个shortcut,就是不改代码只设定环境变量LD_NOW,结果似乎不行,因为也许 resolve NOW仅仅限于被dynamic loading的动态库本身的symbol,比如MF1,MF2,对于动态库所依赖的二层库HF1,HF2他们所依赖的三层库HC1,HC2的 symbol的resolve是否也是如此的private呢?为了保险我设定了private,now,deepbinding三个标志给dlopen 解决了这个难题,其结果达到了这样一个效果在一个程序里实现了近似于静态库的效果,但是绕过了动态库编译链接时候同样symbol被重复define的困 难,这个在静态编译不通过修改代码是无法达到的!


一月十七日当前只有等待等待

这个是一个很小的东西,看一下的代码无法编译:
std::ifstream in("readme.txt");
if (in)
{
      std::stringstream ss;
      ss.rdbuf(in.rdbuf());   // compiler complains no such candidate, it only accept rdbuf without param.
}
而这在在basic_ios里是有定义的!
在basic_stringstream以及它的继承类比如stringstream,istringstream,ostingstream里你丢掉了 一个在basic_ios里定义的这个基本方法:basic_streambuf*  rdbuf(basic_streambuf* sb);原本这个和basic_streambuf*  rdbuf();两个并列让你能够既set又能get streambuf这个对象指针,我去掉了函数模板参数是为了看的清楚。可是当我在stringstream ss;ss.rdbuf(pSB);的时候编译器报错说只有签名是那个不带参数的get的方法有定义,就是说rebuf这个方法不能有参数,可是为什么继 承来的方法不能用呢?而且我在c++网站的例子里偏偏可以用!着实花费了一些时间才明白这个是对于basic_stringstream的特殊情况,网站的例子是iostream没有问题,看到在basic_ios.h的实现时候的注解吗?
     /**
       *  @brief  Changing the underlying buffer.
       *  @param  __sb  The new stream buffer.
       *  @return  The previous stream buffer.
       *
       *  Associates a new buffer with the current stream, and clears the
       *  error state.
       *
       *  Due to historical accidents which the LWG refuses to correct, the
       *  I/O library suffers from a design error:  this function is hidden
       *  in derived classes by overrides of the zero-argument @c rdbuf(),
       *  which is non-virtual for hysterical raisins.  As a result, you
       *  must use explicit qualifications to access this function via any
       *  derived class.  For example:
       *
       *  @code
       *  std::fstream     foo;         // or some other derived type
       *  std::streambuf*  p = .....;
       *
       *  foo.ios::rdbuf(p);            // ios == basic_ios<char>
       *  @endcode
      */
      basic_streambuf<_CharT, _Traits>*
      rdbuf(basic_streambuf<_CharT, _Traits>* __sb);
就是说以上方法只能这样调用ss.ios::rdbuf(in.rdbuf());这个确实是一个奇妙的事情,lost in translation?是模板specialization的时候覆盖了,或者作者压根儿就是抵制这个方法,其实我也不知道我想干什么,因为直接操纵 streambuf应该不是一个好事情,我是不得已而为之,如下你其实没有理由去偷梁换柱的直接替换streambuf也许输出是你唯一的目的,为何要偷 换?我是在我的模拟器里为了模拟http request里的stream用本地的file stream来读文件模拟,其中的代码近来突然有问题才想看看streambuf是何方神圣:
    ifstream in("readme.txt");
    if (in)
    {
        stringstream ss;
        ss << in.rdbuf();
        in.close();
        cout << ss.str() << endl;
    }

一月二十六日当前只有等待等待

你知道linker script吗?这个宝典里提到了,于是我就去把bin-utils里编译文档看ld.pdf的解说。好似醍醐灌顶,又好似甘露穿心,字字珠玑,句句精要。

一月三十日当前只有等待等待

昨天折腾了大半天才把整个编译代码连同脚本送出去,原因是我一直没有在除了debian5.0以外的平台运行过,于是lsb_release的问题始终没有 发现,我写了一个PLATFORM=$(lsb_release ...)的东西,然后在随后的Makefile里直接去ifeq($PLATFORM, "MYFLAG")肯定是不成立的了,换一个变量名啊。这个真的不值一提,不过发现rsync --delete --dry-run --exclude='.svn' -aivr  src dst 用来同步代码确实很好用,如果要把svn下的非管控的文件删除这个oneliner很好用:svn status | grep '^?' | awk '{print $2}' | xargs rm -rf

摘抄以下文档,我本地存一个备份,看rsync的文档太费时间了。
Understanding the output of rsync --itemize-changes
继续读宝典
这里是一个filter的经典的范例,对于我辈饱受动态调用折磨的一个福音,目前我发现了Japan的一个古老的动态库会自行初始化openssl的线程安全的回调函数,这个干扰了其他程序的部署,会有一个线程安全的问题,那么用这个filter就 可以用来过滤一下,z这个基本上就是宝典里的一个范例,我遇到了一个小小的问题,首先使用c++编译器你要去处理malloc/free的修饰名字所以不 会连接到你的filter,所以我图省事就直接用gcc,其次,RTLD_NEXT是整个的核心,这个我以前一直不知道有这个功能,你不需要调用 dlopen,因为你只是要linker提供你一个现成的symbol,而且NEXT的意义重大,manpage都已经说了这个是专门作filter的用 途,这个是我当初百思不得其解的问题,就是我是一个filter的dll我截获了应用的call,我filter之后怎么载传递调用呢?难道再使用 dlopen/dlsym吗?感觉很罗嗦,现在一个RTLD_NEXT就解决了。不过此处有一个小小的诀窍,这个标志定义在dlfcn.h里需要打开宏开 关__USE_GNU可是不能直接定义gcc -D__USE_GNU这个不行,当时迷惑了我好一会,后来才发现你要用-D_GNU_SOURCE这个宏才能打开。


二月二日当前只有等待等待

GNU是一个宝库,浏览欣赏而已。

二月六日当前只有等待等待

宝典就在于它在给你珍宝的同时又给你打开一扇窗让你看到从未看到的风景!准备制作绝对小而再小的elf,你准备好了吗?我存一个本地拷贝,同时把自己的过程也记录下来。elfio? 我有些不耐烦。This is what I need?  a local copy is here.

打开以前下载的64bit elf的文档对照。

Header

The header is found at the start of the ELF file.

Position (32 bit) Position (64 bit) Value
0-3 0-3 Magic number - 0x7F, then 'ELF' in ASCII
4 4 1 = 32 bit, 2 = 64 bit
5 5 1 = little endian, 2 = big endian
6 6 ELF Version
7 7 OS ABI - usually 0 for System V
8-15 8-15 Unused/padding
16-17 16-17 1 = relocatable, 2 = executable, 3 = shared, 4 = core
18-19 18-19 Instruction set - 0x3 = x86, 0x3E = x86_64, 0x28 = ARM, etc.
20-23 20-23 ELF Version
24-27 24-31 Program entry position
28-31 32-39 Program header table position
32-35 40-47 Section header table position
36-39 48-51 Flags - architecture dependent; see note below
40-41 52-53 Header size
42-43 54-55 Size of an entry in the program header table
44-45 56-57 Number of entries in the program header table
46-47 58-59 Size of an entry in the section header table
48-49 60-61 Number of entries in the section header table
50-51 62-63 Index in section header table with the section names
The flags entry can probably be ignored for x86 ELFs, as no flags are actually defined.

Program header

This is an array of N (given in the main header) entries in the following format. Make sure to use the correct version depending on whether the file is 32 bit or 64 bit as the tables are quite different.

32 bit version:

Position Value
0-3 Type of segment (see below)
4-7 The offset in the file that the data for this segment can be found (p_offset)
8-11 Where you should start to put this segment in virtual memory (p_vaddr)
12-15 Undefined for the System V ABI
16-19 Size of the segment in the file (p_filesz)
20-23 Size of the segment in memory (p_memsz)
24-27 Flags (see below)
28-31 The required alignment for this section (must be a power of 2)

64 bit version:

Position Value
0-3 Type of segment (see below)
4-7 Flags (see below)
8-15 The offset in the file that the data for this segment can be found (p_offset)
16-23 Where you should start to put this segment in virtual memory (p_vaddr)
24-31 Undefined for the System V ABI
32-39 Size of the segment in the file (p_filesz)
40-47 Size of the segment in memory (p_memsz)
48-55 The required alignment for this section (must be a power of 2)

Segment types: 0 = null - ignore the entry; 1 = load - clear p_memsz bytes at p_vaddr to 0, then copy p_filesz bytes from p_offset to p_vaddr; 2 = dynamic - requires dynamic linking; 3 = interp - contains a file path to an executable to use as an interpreter for the following segment; 4 = note section. There are more values, but mostly contain architecture/environment specific information, which is probably not required for the majority of ELF files.

Flags: 1 = executable, 2 = writable, 4 = readable.

我现在停下来要去吃饭了,手动编辑elf太难了,因为用汇编器产生elf很麻烦,这里有一个小小的c程序来生成小小的c程序来生成小小的c程序来生成小小的c程序来生成


二月八日当前只有等待等待

怎样生成最小的elf文件呢?我用了一个很长的路径:

1.首先我的汇编代码基本不需要改动,所以,我从之前的.o用objcopy来拷贝出来。

2.然后修改了这个小代码来“拼凑”成一个elf,前提当然是没有什么复杂的调用和section部分吧。

所有的过程都记载在我的注释部分

我的记录是129bytes。

nick@nick-KGP-M-E-D16:/OCZ240/MyProjects/tiny/src$ ./mytiny ; echo $?
42
nick@nick-KGP-M-E-D16:/OCZ240/MyProjects/tiny/src$ wc -c mytiny
129 mytiny

理论上这个应该差不多是极限,除非作以下改动(作者就是这样子的,我没有进一步去做,因为感觉这个有些奇技淫巧了):

a)汇编代码除非使用al使得“立即数”不用4个bytes看以下汇编高亮部分使用了4个bytes。

nick@nick-KGP-M-E-D16:/OCZ240/MyProjects/tiny/src$ objdump -d tiny.o

tiny.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <_start>:
   0:    b8 01 00 00 00           mov    $0x1,%eax
   5:    b3 2a                    mov    $0x2a,%bl
   7:    cd 80                    int    $0x80
b)hack方法来压缩elf头部,这里的意思是让ehr和phr部分重叠,并裁剪掉无用的section部分。我没有仔细去看,大概是可以的,不过我要去修改我的c代码使用自定义的elf header来作。


二月十二日当前只有等待等待

动态库的水很深,对于这样一个基本的不能再基本的编程常识有多少误区呢?这是一个实验,其中main依赖几个动态库如下:
main.exe ==> libHiStor.so,libDepend.so, libNew.so
libHiStor.so ==> libDepend.so, libNew.so
libDepend.so ==> libOld.so
糟糕的是libNew.so 和libOld.so里偏巧定义了相同的函数,signature完全相同,虽然libDepend.so明确告诉linker它是依赖于 libOld.so,而且运行期linker也强调要求libOld.so必须在,可是在运行期,libDepend.so的函数却被libNew.so 替代了,这个是因为main.exe本身要求libNew.so,应该在GOT里就有了定义了,所以,linker也就不再费力去找了。

另一个小的不能再小的小笑话就是花了半个多小时才明白的,在makefile里直接执行程序最后总是报错,茫茫然使用makefile的debug 不得所以然,最后才发现我的main.c里忘记返回,结果make以为程序返回非零是错误。直接调用printf不加#include< stdio.h>导致gcc老是抱怨imcompatible的警告。

这里是一个很好的makefile本身debug的办法,类似于dry-run,或者make --just-print,这个更好--debug=j

这个小恶魔/lib/x86_64-linux-gnu/ld-2.19.so是那个包编译的呢?我居然把它和ld这个executable搞混了,ld是属于binutils的,而此君是glibc的。
此人绝非等闲之辈,十年磨一剑,我可能需要十五年左右。应该要学习一下docbook!!!


二月十三日当前只有等待等待

rpm的macro
%{_topdir}            %{getenv:HOME}/rpmbuild
%{_builddir}          %{_topdir}/BUILD
%{_rpmdir}            %{_topdir}/RPMS
%{_sourcedir}         %{_topdir}/SOURCES
%{_specdir}           %{_topdir}/SPECS
%{_srcrpmdir}         %{_topdir}/SRPMS
%{_buildrootdir}      %{_topdir}/BUILDROOT


二月十六日当前只有等待等待

什么叫做wild goose chase?就是花了大量的时间追逐而一无所获,我发现rpm打包后.jar文件尺寸变小,一直怀疑.jar是类似于二进制文件rpmbuild不应拆 解,看来先入为主的观点导致了一切的盲目追逐,最后才发现两者的尺寸差别是.jar文件被重新打包再重新压缩,这个行为可以被禁止掉:%define __os_install_post %{nil}

二月十七日当前只有等待等待

从google里发现了我以前作的讲义project的slides对我自己充满了崇敬的心情。

二月十八日当前只有等待等待

宝典每天只能读一点。

二月二十三日当前只有等待等待

保存一个东西,我之前从glibc代码里扣出来的一个小玩意和这个有些相似。

二月二十五日当前只有等待等待

早晨起来读《孙子兵法》对比美军在伊拉克阿富汗的遭遇颇有应证的意义。

二月二十六日当前只有等待等待

早晨读宝典这些就是至理名言,虽然通俗简单,可是昨天还是有人发了一千封的邮件来辩驳。
Incompatible Libraries
When a new version of a library is binary-incompatible with the old one the soname needs to change. In C, there are four basic reasons that a library would cease to be binary compatible:
1. The behavior of a function changes so that it no longer meets its original specification,
2. Exported data items change (exception: adding optional items to the ends of structures is okay, as long as those structures are only allocated within the library).
3. An exported function is removed.
4. The interface of an exported function changes.

For C++ (and other languages supporting compiled-in templates and/or compiled dispatched methods), the situation is trickier. All of the above issues apply, plus many more issues. The reason is that some information is implemented “under the covers” in the compiled code, resulting in dependencies that may not be obvious if you don’t know how C++ is typically implemented. Strictly speaking, they aren’t “new” issues, it’s just that compiled C++ code invokes them in ways that may be surprising to you.
The following is a (probably incomplete) list of things that you can and can’t do in C++ and retain binary compatibility (these were originally reported by Troll Tech’s Technical FAQ; a more up-to-date list is in KDE’s Policies/Binary Compatibility Issues With C++ 9 ):
1. add reimplementations of virtual functions (unless it it safe for older binaries to call the original implementation), because the compiler evaluates SuperClass::virtualFunction() calls at compile-time (not link-time).
2. add or remove virtual member functions, because this would change the size and layout of the vtbl of every subclass.
3. change the type of any data members or move any data members that can be accessed via inline member functions.
4. change the class hierarchy, except to add new leaves.
5. add or remove private data members, because this would change the size and layout of every subclass.
6. remove public or protected member functions unless they are inline.
7. make a public or protected member function inline.
8. change what an inline function does, unless the old version continues working.
9. change the access rights (i.e. public, protected or private) of a member function in a portable program, because some compilers mangle the access rights into the function name.


三月二日当前只有等待等待

need for speed很多时候就是要快,要下载这个List里的文件并且要作md5验证。需要载下载补丁,于是又改动了一下下

三月八日当前只有等待等待

在编译Linux的文件系统的时候,我发现我的磁盘操作变得非常慢,dmesg|tail显示了lsi的raid卡控制的分区可能有坏的sector吧。
nick@nick-KGP-M-E-D16:~/Downloads/daemon-0.6.4$ dmesg |tail
[7316380.172752] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[7316380.172767] sd 4:1:0:0: [sdf] 
[7316380.172775] Sense Key : Medium Error [current]
[7316380.172800] Info fld=0x1c6085a8
[7316380.172802] sd 4:1:0:0: [sdf] 
[7316380.172804] Add. Sense: Unrecovered read error
[7316380.172806] sd 4:1:0:0: [sdf] CDB:
[7316380.172808] Read(10): 28 00 38 c1 0b 28 00 00 08 00
[7316380.172816] end_request: critical medium error, dev sdf, sector 952175400
[7316380.173056] EXT4-fs warning (device sdf): __ext4_read_dirblock:902: error reading directory block (ino 29758638, block 8)
nick@nick-KGP-M-E-D16:~/Downloads/daemon-0.6.4$ lspci |grep LSI
06:00.0 Serial Attached SCSI controller: LSI Logic / Symbios Logic SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (rev 03)
找到了关于raid卡的信息。下载了一个lsi的工具包安装包是这个。使用sas2ircu别忘了sudo,首先sudo sas2ircu LIST告诉你LSI的controller id,比如0,然后就可以sas2ircu 0 DISPLAY不过这个只能报信息,无法manage。
有一大堆的sg的scsi命令工具,但是这个卡很多都不支持。下载了LSI的mpt的user guide.

三月九日当前只有等待等待

这个文档有些用是关于sas2 LSI的raid card。

三月十日当前只有等待等待

这个文档是什么时候下载的?似乎很有用,是关于qemu的debug的。

三月十二日当前只有等待等待

alphago又赢了李世石,作为兴趣搜索了一些论文,monte carlo go,这个好像是alphago最原始的框架吧?其实看起来梦特卡罗算法本身并不复杂,困难的是所谓的exploration/exploitation的delima,这里有一个所谓的UCB的解决算法, 这个算法的核心论文是这一篇吗?说白了也很简单,两个因子,一个是采用此种策略的胜率,一个是采用此种策略在以往所有使用的频率,前者鼓励采用成熟的已知 的方案,后者要鼓励创新,所以,后者用了倒数,当然要添加一些数学的花样开个根号,娶个对数加个常量,不能把两者相提并论罢了。如果能够把ucb也能做成 回馈而不是这个定论的算法该多好啊。其中不停的提到regret让我很迷惑,谷歌才知道是一个对策论的概念

三月十五日当前只有等待等待

我的ubuntu显示有些问题,比如terminal的全黑实际上是选色的问题,要把profile/color的颜色改掉。gnuGo3.8的手册

三月二十日当前只有等待等待

谷歌的alphago的论文。 遇到一个有趣的问题。以下Derived class的constructor总是报错说baseCount不是它的成员,这个实际上是对的,因为他是Base的成员,所以,在 constructor里通过:进行的直接调用各个成员的constructor的方式是严格只能访问自己定义的成员变量,如果一定要给 baseCount初始化,那么就需要使用成员Base的constructor,把baseCount(0)改成Base()。这个是一个典型的应用例 子。
class Base
{
public:
Base():baseCount(0)  {}
  int baseCount;
};
class Derived: public Base
{
public:
    Derived():baseCount(0){}  //
};

三月二十七日当前只有等待等待

关于动态库的又一篇宝典

四月二十七日当前只有等待等待

不在沉默中消失就在沉默中爆发?我要测试一个服务当机后的处置,QA给出了一个办法,设置route,就是把那个目的地转向一个无人接听的ip,route -host destIP gw dumpIp,结束后可以删除这个route,route delete destIp。这个做法很实用。昨天和同事一起实验如果在本机发送请求给本地服务使用127.0.0.1和本机ip究竟是否会有额外的开销,同事使用 tcpdump显示请求并没有被发送出去,也就是说linux很smart。

五月四日当前只有等待等待

声明一个常数字符串应该怎样才最好?第二个比第一个好的原因在于数组变量和指针还是有差别的因为编译器知道数组地址是一个不可以改变的指针,所以可以被优 化,甚至于它根本不需要建立变量名,最后直接使用literal,而且字符串存储还可以使用hash包括长字串包含短字串,比如第二个是第一个的子串,存 储只有第一个,子串只是一个偏移和长度就可以了。详细来自宝典
1.  const char* ptr =" hello world!";
2. const char array[] = "hello";

找到一柄利器elfutils,实际上这个是binutils分离出来的,不过你需要的东东都有了。实际上可以更小,你只需要libelf,这个比自己去写要容易多了。


五月五日当前只有等待等待

gdb的cheatsheet。在eclipse里unresolved include path很恼人,在c/c++ general的preprocessor include path里把provider里的CDT GCC built-in compiler settings提前。
c的struct的初始化可以使用.member来防止成员顺序改变的情况,作为class同样可以这样作,但通常都是使用constructor初始化。同时在constructor的初始化部分是class的原生变量,对于继承来的变量是不可以的。
struct S{int i,j,k;};  S s={.i=0,.j=1,.k=2};
mtrace应该是个好东西,通常可以这样使用在代码里#include <mcheck.h>并且在开始部分包含mtrace() ;调用,如果设定了环境变量export MALLOC_TRACE=/tmp/mtrace.log那么你就会看到输出部分。然后使用addr2line可以获得分配内存代码行号,对于系统分配 的内存addr2line似乎无法返回正确信息?

五月六日当前只有等待等待

这是一个古老的问题,如果你没有遇到说明你很少编程,至少很少使用gnu的东西,遇到gcc抱怨offset_t没有定义的话,不要问肯定是什么宏没有定义对,但是是什么呢?看了这里就明白了,不要直接去定义文件尺寸相关的宏,而是需要定义_GNU_SOURCE,这个问题几个月前我就遇到过了,耗费了大半天,现在又来了一遍,可见学而时习之的意思是什么了,记忆力阿。

费了一些力气单独编译libelf,这个是在elfutils里的一个小模块,但是它也依赖于lib的一两个文件比如crc之类的,总之是一个可以 独立出来的东西。然而编译完了却才意识到不知这个怎么用,当然elf_begin。。.一步一步使用是可以看明白,不过究竟这个有多么的趁手就不知道了。 编译的过程注意有亮点,一个是整个的elfutils有一个config.h,其次需要lib这个单独的模块中的一些头文件,你可以不使用g++而是直接 使用gcc来编译动态库,不过就是要之前说的定义_GNU_SOURCE了。


五月七日当前只有等待等待

其实我应该更加感兴趣的是“矮人”,这里是dwarf2的文档,libdwarf 依赖于libdw。读了没有两页纸我就知道这个不是我要的,它太接近于底层的实现了,正如设计思想,这个是独立于语言和实现的通用的debug信息表达方 式,非常非常的接近汇编的架构,我想这个也是有意味之因为你得到这个也要执行才能获得真正的值,那么直接产生了代码去执行了。google了一下,似乎这 个的作者是ulrich drepper,此人很有来头,我还在读他的宝典关于动态库的。这里是他的关于内存的。
这里有些openbook。下载了这本古老的书--linux device driver 3rd edition.

五月二十日当前只有等待等待

一切起源于一封来信,一个网友搜索到我保存的ubuntu lucid的源代码,他说他要一个收音机调谐的驱动,我对于此其实一无所知,建议他编译内核模块如下:
1. You don't want to compile the whole kernel because it is too much effort.
2. so you only need to compile this driver module only. This is guide of how to compile kernel module and install module.
http://askubuntu.com/questions/515407/how-recipe-to-build-only-one-kernel-module
here I repeat what is above:
a) to prepare kernel building, you need to install all compilation tools like gcc etc.
sudo apt-get install build-essential
b) you need to install those kernel headers and source to prepare compile your kernel driver.
sudo apt-get install linux-headers-$(uname -r)
c) download dsbr100.c to your computer to prepare building.
d) create a Makefile to build kernel module
echo "obj-m += dsbr100.o" > Makefile

e) build kernel module

make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

f) install the kernel module
sudo insmod ./dsbr100.ko

g) to verify if this module has been installed
lsmod | grep dsbr100

其实这里有一些疑问,就是关于编译内核模块及其安装部分,是否insmod可以直接安装呢.ko呢?我原来以为是,实际上还有一些其他的模块文件被编译产生了。

我花了一两天来了解什么是puppylinux,看来这个是一个搭积木的linux发行版,它使用一些脚本直接从 ubuntu/debian/slack等等下载编译好的包然后裁剪,当然似乎有些改变应该不大巴?于是我试图使用老办法用debootstrap来验 证,不过第一步之后我又陷入了以前的迷惑,什么是second-stage呢?后来看以前的笔记和google又毒了他的manpage才明白,第一步是 下载安装所有的发行版(suite)和架构(arch)的包,第二部是要在目标机器或者模拟器下载配置,所以,对于同质的本地操作系统我使用chroot 就足够了,还没看明白debootstrap在second-stage究竟要做什么?研究了半天后来突然发现实际上puppylucid本身就已经自带 了他需要的模块,只需要普通的modprobe就可以了。其实这个过程很有意义因为他是每一个使用linux都会遇到的问题,你的应用需要特定的驱动怎么 办?windows用户大都要求助于开发者打包自带驱动,linux下非万不得已是不提倡自行编译驱动的,多半module里有,这个要第一考虑。毕竟编 译内核单单设置编译环境就是一个不小的工作。


五月二十九u日当前只有等待等待

v4l2的驱动下载的文件。这些是所谓driver writer的文档,而不是应用开发者需要关心的。

五月三十日当前只有等待等待

v4l2的完整的user api doc,之前的是kernel mode的相关的api 说明。这些user mode就好懂了。

五月三十一日当前只有等待等待

ubuntu 14.04的源码1234,实际上是包的源码,并非真正的文件系统?当然是了,因为debootstrap也是从debian的网站下载,不过是binary+target的形式。

六月二日当前只有等待等待

v4l2究竟是什么以前用过但是不知所云,kernelside的story在这里。1, 2, 3, 4, 5a, 5b, 6a, 6b, 7

六月五日当前只有等待等待

下载linuxtv的源码,也就是v4l2的主干?在这里有一个说明:
git clone git://github.com/torvalds/linux.git v4l-dvb    (actually I download from this: https://git.linuxtv.org/linux.git)

    cd v4l-dvb

    git remote add linuxtv git://linuxtv.org/media_tree.git

    git remote update
    git checkout -b media-master remotes/linuxtv/master

If you want to clone a different repository, just replace the URL at the

    git remote add line above.

In order to update your repository, you should do:

    git pull . remotes/linuxtv/master

And to put your work on top of a stanging branch:

    git rebase remotes/linuxtv/master

六月八日当前只有等待等待

printk怎样打印在console呢?要看syslog的manpage,cat /proc/sys/kernel/printk显示了四个数字,其中第一个是console_loglevel这个决定了如果你的printk的 loglevel比它小的话就能打印了。怎么知道对应的KERN_INFO之类的宏的值呢?看这里吧:/usr/src/linux-headers- 3.16.0-60/include/linux/kern_levels.h
#define KERN_EMERG    KERN_SOH "0"    /* system is unusable */
#define KERN_ALERT    KERN_SOH "1"    /* action must be taken immediately */
#define KERN_CRIT    KERN_SOH "2"    /* critical conditions */
#define KERN_ERR    KERN_SOH "3"    /* error conditions */
#define KERN_WARNING    KERN_SOH "4"    /* warning conditions */
#define KERN_NOTICE    KERN_SOH "5"    /* normal but significant condition */
#define KERN_INFO    KERN_SOH "6"    /* informational */
#define KERN_DEBUG    KERN_SOH "7"    /* debug-level messages */

#define KERN_DEFAULT    KERN_SOH "d"    /* the default kernel loglevel */
可是在ubuntu下怎么写入呢?并非如此简单:sudo echo "7 1 1 7" > /proc/sys/kernel/printk会报说permission,奇怪吗?echo有玄机的只能这样子: echo "7 1 1 7" |sudo tee /proc/sys/kernel/printk
然后你就能在console看到printk的message了吗?不行的因为ubuntu的console不是真的console是xterm,你只能用真console登录,比如ctrl+alt+F1-6默认7是我的gui。

六月九日当前只有等待等待

关于iSCSI设备的连接是如下过程:
0.首先安装工具包ubuntu下是open-iscsi-utils:
sudo apt-get install open-iscsi-utils
1.发现你本机的iSCSI iqn number,这个是你的host的initiator的iqn:
nick@nick-KGP-M-E-D16:~$ iscsi-iname
iqn.2005-03.org.open-iscsi:a9d551e9916
2。发现iscsi target:
nick@nick-KGP-M-E-D16:~$ sudo iscsiadm -m discovery -t st -p 192.168.1.251
192.168.1.251:3260,1 iqn.2000-01.com.synology:DiskStation.Target-1.f354401d16
[fe80::211:32ff:fe29:9731]:3260,1 iqn.2000-01.com.synology:DiskStation.Target-1.f354401d16
nick@nick-KGP-M-E-D16:~$
3. login iscsi target (in-secure mode, I didn't setup chap user in target)
nick@nick-KGP-M-E-D16:~$ sudo iscsiadm -m node -p 192.168.1.251:3260 -l
Logging in to [iface: default, target: iqn.2000-01.com.synology:DiskStation.Target-1.f354401d16, portal: 192.168.1.251,3260] (multiple)
Login to [iface: default, target: iqn.2000-01.com.synology:DiskStation.Target-1.f354401d16, portal: 192.168.1.251,3260] successful.
4. 发现scsi设备,使用fdisk -l列表所有硬盘发现是/dev/sdh
sudo sg_inq --page=0x83 /dev/sdh确认这个是synology的iscsi硬盘
5。格式化磁盘:
nick@nick-KGP-M-E-D16:~$ sudo fdisk /dev/sdh
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0xa32cbc02.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-2097151, default 2048): 2048
Last sector, +sectors or +size{K,M,G} (2048-2097151, default 2097151): 2097151

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): 83

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
nick@nick-KGP-M-E-D16:~$
6。生成文件系统:
nick@nick-KGP-M-E-D16:~$ sudo mkfs.ext3 /dev/sdh1
mke2fs 1.42.9 (4-Feb-2014)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
65536 inodes, 261888 blocks
13094 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=268435456
8 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376

Allocating group tables: done                           
Writing inode tables: done                           
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
7。mount 文件系统
sudo mkdir /mnt/iscsi
sudo mount /dev/sdh1 /mnt/iscsi
8。我现在发现我的iscsi lun太小了,于是在synology NAS上更改了lun的大小,可是client端没有发现变化,只能logout而且好像还要删除当前的node才行
sudo iscsiadm -m node -p 192.168.1.251:3260 --logout
sudo iscsiadm -m node -p 192.168.1.251:3260 -o delete
sudo iscsiadm -m discovery -p 192.168.1.251
sudo iscsiadm -m node -p 192.168.1.251:3260 -l
9。现在lun是有那么大了从1G变为5G,但是我之前的文件系统并没有扩大,于是这个又是一个大问题
a)sudo umount /dev/sdh1
b)去除journal变为ext2这样才能行
sudo tune2fs -O ^has_journal /dev/sdh1
c)检查一下:
e2fsck -f /dev/sda1
d) resize  文件系统,这里5000M是一个保守的做法,之前我采用fdisk输出的/dev/sdh的数值结果失败了,应该要小一点巴?
sudo resize2fs /dev/sdh1 5000M
e) 删除分区重新创建
sudo fdisk /dev/sdh
nick@nick-KGP-M-E-D16:~/Documents/personal$ sudo fdisk /dev/sdh

Command (m for help): d
Selected partition 1

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1):
Using default value 1
First sector (2048-10485759, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-10485759, default 10485759):
Using default value 10485759

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
f)添加journal
sudo tune2fs -j /dev/sdh1

六月十三日当前只有等待等待

关于linux kernel module programming。是从这里下载的。

六月十四日当前只有等待等待

vim的cheatsheet

六月十五日当前只有等待等待

这个关于LKM的文章太老了点,其中的例子有些在kernel3.x改掉了,这个看起来是比较新的。这个是第二章
作者非常的精细,这个是额外的收获。
The %[^\n]%*c uses the scanset specifiers, which are represented by %[] to use the ^ character to stop reading after the first occurrence of the \n character. In addition, the %*c ignores the trailing character, ensuring that the subsequent getchar() function works as required. Essentially, the scanf() code just reads in a sentence. If scanf() was used with a regular %s call then the string would terminated at the first occurrence of the space character.

六月十九日当前只有等待等待

对于char device文件,我从ubuntu 的xterm来cat就看不到任何输出,着实困惑了我好一会儿,后来才意识到这个和printk的log message不能显示是一个原因吧,只有在真正的console才行,在graphic mode下都有问题。这个是lkm的第三篇文章。其中的code在这里

六月二十二日当前只有等待等待

这里设置vncserver为一个服务。

六月二十五日当前只有等待等待

关于X windows的文档

六月二十七日当前只有等待等待

fix了一个小问题,就是我之前的capture会退出而没有捕捉任何一帧图像,debug时候又正常,然后意识到要开始的时候休眠一两秒,随后才debug发现是camera一开始没有立刻ready工作要处理EAGAIN之前仅仅处理了EINTER。

六月三十日当前只有等待等待

一定要读手册,boot的切换不是自动的。这个网站比beagleboard 官方还好?对于.img文件你可以直接使用fdisk来看他的分区情况,然后mount是要使用-o loop,offset=xxx来的,这里的xxx是偏移,大体上就是第一个扇区sector的偏移,通常unit是512bytes的。我买的是比较早 期的rev. 5A就是xam3359azcz100的处理器,一定要按住boot才可以断点加电切换到sd卡的启动,否则都是默认的emmc的启动。添加一个u-boot的git

七月四日当前只有等待等待

debian的image在这里。这里是作者的私人网页指导刷emmc

七月五日当前只有等待等待

这里是一篇很好的linux asm入门介绍。我喜欢他的syscall table,不过这个好似是很老版本的了。本地保存一份TI的am335x处理器手册TI的关于beagleboard的支持,这是boot的问答,本地存一份

七月六日当前只有等待等待

这个似乎是一个成熟的版本。但是只有ubuntu14.04可以,12.04有问题。我的古老的一个usb dongle使用的是zydas的芯片,缺少firmware,找了很久才在这里找到。阅读其中的README知道需要把其中的firmware拷贝到我的beaglebone的/lib/firmware/zd1211/目录下。

七月七日当前只有等待等待

使用wireless-tool似乎是一个噩梦,应该使用network-manager,即便是他的命令行也好:nmcli
不过最后我彻底放弃了,因为dhclient的因素吗?其实这个几乎就可以了,但是总有一些错误,以后再尝试吧,目前就用static的设置吧。
这个是/etc/network/interface里关于无线的样板设置:
auto wlan0
iface wlan0 inet static
address 192.168.1.150
netmask 255.255.255.0
gateway 192.168.1.1
wpa-essid MYESSID12345
wpa-psk MYPASSWORD$1234567
其后bring it up: sudo ifup -v wlan0
关于crda的问题,我找到了这个我信服的原因,要必须把rfkill编译成Module。这里有一个设置不知道是否可以:在/etc/rc.local里设置iw reg set US

七月八日当前只有等待等待

把原有的ubuntu 14.04的runlevel从2改为5,这个是在/etc/init/rc-sysinit.conf,这种做法是不对的,应该是在启动时候传入的参 数,这个在ubuntu使用grub的设置和U-boot不同,我也没有找到,总之,简单安装ubuntu-desktop组件不足以进入图形界面。这个 才是beagleboneblack的官方网页TI的AM3359处理器官网。AM3359 sitara的wikischematic, datasheet, tech-reference,u-boot user guide.
我觉得TI的sdk应该要去学习一下,这个是学习的重点。arago的开始步骤
这个也非常值得研究。我在编译TI sdk时候遇到很多编译错误,因为我的ubuntu有很多包没有安装,不想改了,就下载了docker来尝试虚拟机的编译环境。
删除了docker,因为使用TI的sdk导致我的主机反复死机,不知道原因,这里有关tftp的介绍,ti的script太傻瓜了,除了问题什么也不知道。TIsdk保存在这里。

七月十日当前只有等待等待

制作initrd的文档在Linux kernel的文件里给的例子:(创建和解压缩)
find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img
gzip -cd /boot/imagefile.img | cpio -imd --quiet
tftp的启动在ubuntu14.04是有问题的,几乎所有的人都说启动service xinetd,它的配置文件是/etc/xinetd.d/tftp,可是tftp只是寻找/srv/tftp的目录,所以,这个配置文件肯定不对。
有一个缺失的链条,就是TI AM335x处理器的boot的过程,这一点的缺失导致你不能明白怎样才能boot:kernel是通过tftp下载,文件系统是通过nfs,这个做法是 最好的,因为优点是你可以轻松修改,不用重新灌装非常慢且容易磨损的microSD卡。但是这里有一个巨大的问号就是这些是在哪里设置的?毫无疑问是在 bootloader,但是是哪一个?看这里就知道有 四个stage:1. ROM的TI的原装的bootloader,这个不能改也不能接触。2. SPL(Secondary Program Loader)这个编译为MLO文件,3. u-boot这个才是你写你的uEnv.txt的脚本的地方。4. Linux kernel
我们需要做的是第三步,可是前面两步怎么做到的,核心就是怎样boot BBB by UART,这个就是核心问题,这个也是使用TI SDK失败的一个环节。这个问题解决了那么tftp+nfs以及编译kernel和用buildroot来编译文件系统相对来说都是比较容易的,至少我是到过哪里的。BBB官方网页也有类似的步骤
把我的ubuntu14.04搞死的也许是uart,或者是usb接口,总之我的bbb应该是毁了,无法启动,任何模式下都不能power,而且。。。
研究了半天也不明白到底element14和mbest哪个好,中国的应该要便宜才对啊?下载了一个中文版的手册,区别在于有针对开发者的部分,而非纯粹的用户手册。

七月十二日当前只有等待等待

这里是制作文件系统的命令。我的改动如下:
debootstrap --no-check-gpg --foreign --keep-debootstrap-dir --arch=armhf stable /opt/buildroot/ http://mirrordirector.raspbian.org/raspbian
cp /usr/bin/qemu-arm-static /opt/buildroot/usr/bin
mount /dev /opt/buildroot/dev -o bind
mount /dev/pts /opt/buildroot/dev/pts -o bind
mount /sys /opt/buildroot/sys -o bind
mount /proc /opt/buildroot/proc -o bind
chroot /opt/buildroot/ /debootstrap/debootstrap --second-stage
(wait, this will take time)
(check using mount if all the bindmounts are still present. re-bind them if they're not, in case debootstrap has unmounted them)
chroot /opt/buildroot vi /etc/apt/sources.list
(remove the default, set deb http://ftp.us.debian.org/debian stable main contrib non-free and deb-src http://ftp.us.debian.org/debian stable main contrib non-free)


chroot /opt/buildroot/ apt-get update
(in order to avoid locale error, we need to setup locale... this is  a GUI!!!)
chroot /opt/buildroot/ dpkg-reconfigure locales
(you either manually add en_US.UTF-8 UTF-8 to /etc/locale.gen)
chroot /opt/buildroot/ /usr/sbin/locale-gen en_US.UTF-8
(关于这个问题看这里。)

chroot /opt/buildroot/ apt-get install -y build-essential
chroot /opt/buildroot/ apt-get build-dep -y u-boot

七月十五日当前只有等待等待

旧的beagleboneblack可能烧坏了,新的板子来了实验uboot,总算小有心得。我这才明白了一点所谓的4阶段boot的实现方式,使用现成的 MLO可以正确加载emmc,这个速度足够了,我可以把它当作是一个可擦写的闪存来写我的启动脚本(这个真的是废话,因为就是这样设计的,我自己没有意识 到而已。)那么内核大小适合tftp下载。配置tftpd的过程很不清楚,要看manpage,说的很清楚是在 /etc/inetd.conf里配置的,在所谓的/etc/xinet.d/tftp下是否有效我还不清楚。总之我把俩个都配置了,之前只是修改 xinetd的配置无效。u-boot之所以能够让你interactive还能够储存env原因是MLO加载了所谓的nand,u-boot的环境变量 都存在了nand里面。所以我们不需要关心第一和二阶段boot,就是用u-boot来配置就好了。我把范本的uEnv.txt里加载内核从emmc改为 了从tftp下载。好像只需要设置serverip=192.168.1.115就可以了,不需要使用tftpboot,令我吃惊的是单单运行dhcp就 可以自动下载zImage,我一开始还多余的把zImage转为uImage,发现完全不需要??这里得益于这些设置:
kernel_file=zImage
loadaddr=0x82000000
loadkernel=dhcp
在启动u-boot的过程中enter打断autoload,一步一步查询每个变量。。。我觉得也许是nandboot?
我对于使用picocom还是minicom或者是kermit还是直接使用screen感到迷惑,这究竟有什么区别呢? TI有大量的资料,但是都是对于成熟开发者的,所以有很多没有说的很细致。
	mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 -n "Linux kernel" -d arch/arm/boot/zImage uImage

七月十七日当前只有等待等待

一步一步来,首先,我使用emmc作为uEnv.txt的存储地(我觉得应该也要改成tftp否则还是很难debug修改),但是至少使用以下来进行tftp kernel/initrd/fdt,应用nfs来作文件系统,但是遇到了启动失败,似乎root=参数不对吧?或者
console=ttyO0,115200n8
kernel_file=zImage
initrd_file=initrd.img
fdt_file=am335x-boneblack.dtb

loadaddr=0x82000000
initrd_addr=0x88080000
fdtaddr=0x88000000

initrd_high=0xffffffff
fdt_high=0xffffffff

ipaddr=192.168.1.207
serverip=192.168.1.115
loadkernel=tftp ${loadaddr} ${kernel_file}
loadinitrd=tftp ${initrd_addr} ${initrd_file}; setenv initrd_size ${filesize}
loadfdt=tftp ${fdtaddr} dtbs/${fdt_file}

loadfiles=run loadkernel; run loadinitrd; run loadfdt
nfsbootargs=setenv bootargs console=${console} ${optargs} root=/dev/nfs rw nfsroot=${serverip}:/BigDisk/beagleboneblack/debian/rootfs ip=${ipaddr}:::::eth0 ${systemd}
uenvcmd=run loadkernel; run loadinitrd; run loadfdt; run nfsbootargs; bootz ${loadaddr} -  ${fdtaddr}
如果你想知道怎样才能load一个uEnv.txt到内存的话,这个就是参考(核心就是理解所谓的loadaddr,我原来以为这个是一个特定的地址比如kernel image的专有地址,现在看来是通用的loading)这个分析至关重要
importbootenv=echo Importing environment from mmc ...; env import -t $loadaddr $filesize
我的做法就是这样子:tftp ${loadaddr} uEnv.txt 然后: env import -t ${loadaddr} ${filesize}这样就从内存中读取了uEnv.txt的内容。
研读TI的wiki是必须的,但是时间阿。
无法做到完全自动,但是解决了基本的目的:1.uEnv.txt可以通过tftp下载并加载。2.kernel可以通过tftp下载并启动。3.实现使用 nfs作为文件系统。其中第一步加载了我的主机上的uEnv.txt后u-boot抱怨说uenvcmd没有定义,拒绝继续,我只能手动执行我的run uenvcmd,不知道u-boot里的test -n ${uenvcmd} 为什么返回不正确?因为我的emmc上的uEnv.txt仅仅是下载主机的uEnv.txt这样emmc上的定义的uenvcmd变量就被覆盖了,但是u -boot却不接受还是???不过,仅仅一行手动执行我也可以满足了,下一步就是要开始编译自己的内核和文件系统了。这个才是关键。

七月十八日当前只有等待等待

尝试这个pre-configured ubuntu image
直接使用debootstrap有问题,应该使用
qemu-debootstrap.
这里值得参考。安装toolchain: sudo apt-get install gcc-arm-linux-gnueabi
摸索中,决定尝试官网的编译流程。

七月二十一日当前只有等待等待

toolchain里export CROSS_COMPILE=arm-linux-gnueabihf-才是我要的,之前的都是armel,我需要的armhf,所以相应的下载这个 gcc-arm-linux-gnueabihf libncurses5 libncurses5-dev libelf-dev
ubuntu的内核代码直接git这里: git clone git://kernel.ubuntu.com/ubuntu/ubuntu-<release codename>.git
我使用的qemu-debootstrap我看代码确实没有什么神器的,仅仅就是帮你拷贝了一下qemu-arm-static到/usr/bin,这个我手动也是如此。不过我现在才意识到我选的arch实际上是32位的,这个也许是chroot失败的原因吧?
目前我尝试在开发主机上预作文件系统,使用debian/ubuntu的debootstrap下载,然后chroot/qemu来在主机上下载/编译内 核,选择与我的主机内核/文件系统相同的ubuntu-trusty,这样我认为chroot是可以达到足够的相似度的,使用docker有狠多我现在还 不理解的地方,比如难道是运行另一个版本的内核吗?否则怎么能够在chroot的基础上完全模拟?另一个优点就是如果要在beaglebone black上用官网的预制系统来下载源码编译速度要慢不少。而纯粹的在开发主机上使用交叉编译也许是最快的,我想比较一下再作交叉编译。或者直接使用 Linaro,这个应该可以满足我的需要。再一个选择就是看TI的所谓sdk,他们有一个更加高效检验过的工作流程,似乎不需要下载安装linaro就可 以直接开发,也许是打包了linaro之类的?
看了一下http://ports.ubuntu.com/ubuntu-ports/dists/trusty/main/实际是有一个arm64的,但是检查qemu-debootstrap发现它还不支持这个arch。所以只能之际使用debootstrap。
sudo debootstrap --arch=arm64  --keyring=/usr/share/keyrings/ubuntu-archive-keyring.gpg --foreign --keep-debootstrap-dir trusty trusty-arm64-rootfs
然后你要知道你需要的是qemu的64位的arm static binary来chroot,所以拷贝的是/usr/bin/qemu-aarch64-static,而之前我拷贝的qemu-arm-static应 该是给32位的吧?chroot成功后就是直接在/debootstrap下执行./debootstrap --second-stage

七月二十二日当前只有等待等待

几条路都尝试了,不行,所以,还是回到TI的路上,这个是成功率最高的,直接使用linaro对于我来说和使用gnu toolchain没有太大的差别,关键不在toolchain而是一些kernel的配置,当然自己编译文件系统也是麻烦事情,可是两者的重要性不同。
这里是TI的所有的tool。还有一些training也很好,解决了什么和为什么的问题。发现sdk有我所需要的所有只是我没有意识到而已。太棒了。

七月二十三日当前只有等待等待

证 实了tftp的配置是/etc/inetd.conf里的启动参数,修改/etc/xinetd.d/tftp并无效果,但是启动tftp依然是用 xinetd的service。奇怪。运行了setup.sh以后在bin下有一个setupBoard.minicom,可以作为开机设置的工具,因为 我每次使用minicom都不够快能够进入interactive模式。不过怎样才能设置正确的uEvn.txt呢?我买的logitech的老鼠标总是 抱怨,于是需要关闭printk的msg,必须改变log level。echo 4 > /proc/sys/kernel/printk 或者dmesg -n 4
arago有一些demo可以看看。

七月二十四日当前只有等待等待

这里是ti-sdk详细的解说,绝对的指引。

七月二十五日当前只有等待等待

TI的所谓processor sdk似乎早已停止了,或者转向别的新的型号,的确am335x是一个低端的入门级别的。我目前卡在文件系统,看来最系统简单的就是yocto,我一直不 明白为什么几年前起我就一直抵触这个工具,包括linaro,也许是总想自己做一遍吧,但是有了基本的linux from scratch的体会就应该意识到这个工作相当的费力不讨好,使用现有工具是不二选择。对于sdk编译文件系统的yocto错误部分,我无从探究因为使用 yocto需要我自己重新尝试,从这个入门的教程开始吧。这个是什么

七月二十六日当前只有等待等待

此人说出了一些众人都犯的错误,究竟bootcmd是谁设定的?你如果知道beaglebone没有真正的nand来存储类似bios的设置的话,就应该明白这个道理。
我按照jumpnow的详细解说编译的yocto的内核及其文件系统使用microsd卡是可以正确启动,但是如果使用nfs mount rootfs的话报错说Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,255) ,经过google,我自己分析应该是内核没有编译nfs的rootfs的支持,这样子就要重新配置kernel,命令是这样子的:
source poky-krogoth/oe-init-build-env bbb/build/
bitbake linux-stable -c menuconfig
对于nfs+tftp的解说这个比较准确一些。果不其然,在config里增加了nfs rootfs的支持之后就可以正确启动了。
U-Boot> set autoload no
set ethaddr a0:f6:fd:8a:e9:0b
U-Boot> dhcp
U-Boot> set serverip 192.168.1.115
U-Boot> setenv bootargs console=${console} root=/dev/nfs rw rootfstype=nfs ip=dhcp nfsroot=192.168.1.115:/BigDisk/ti-sdk/rootfs
U-Boot> tftp ${loadaddr} zImage
U-Boot> tftp ${fdtaddr} ${fdtfile}
U-Boot> bootz ${loadaddr} - ${fdtaddr}

七月二十七日当前只有等待等待

这里解说了一部分谜语关于boot.scr.uimg。
这个是后续解决package的好办法,作者提出了通常的四五六种办法,真是真正的实干家的经验。

七月三十日当前只有等待等待

yocto的package没有问题了。遇到htop包出错,就直接删除重新安装。jumpnowtek.com网站非常的有帮助。现在我想最便捷的道路是使用qt,这个我是纯粹的外行,从Helloworld学起。首先,编译,最简单的是使用
qmake -project "QT+=widgets"
否则默认不会帮你把widgets加上的。然后再运行qmake就帮助你生成了Makefile了,否则自己编译命令行非常的复杂。qt的helloworld运行失败抱怨基本的包Missing我以为是qt的不完整安装,因为压根没有编译这些包。这里有增加qt的指示,尝试中。

七月三十一日当前只有等待等待

TI的所谓的am335x-pru0-fw无法加载的问题是源于TI的sample里的PRU_RPMsg_Echo_Interrupt0.out要拷贝到 /lib/firmware/pru/下,然后建立一个/lib/firmware/am335x-pru0-fw的link,同理是后缀为1的fw。但 是我的启动还是失败了。回到了yocto结果在udev的启动中失败了。后来发现am335x-pm-firmware.elf也需要就又可以启动了。
试图编译directfb,结果失败,原因也许在这里:DISTRO_FEATURES_append = "directfb sysvinit"  DISTRO_FEATURES_remove = "x11 wayland"注意,在引号之后加上空格“。

八月二日当前只有等待等待

我个人觉得yocto太复杂了,虽然有很多优点,可是配置的学习是一个相当的过程,也许buildroot更加的适合我,这个是两者的比较,这个是buildroot的一个lab。这个包罗万象还没有时间去看。yocto对于cpu的利用达到了极致,buildroot就是追求一个简单。

八月三日当前只有等待等待

在你的tftp目录下创建一个boot.scr.uimg,这样子当你的serverip/dhcp等等ready的时候,u-boot会自动下载你的这个 脚本使用tftp,所以是一个你本地的启动脚本,在这里面我把我的启动内核及其dtb文件和rootfs的nfs设置写在里面了:
nick@nick-KGP-M-E-D16:/BigDisk/ti-sdk/boot$ cat boot.scr
echo "this is boot.scr.uimg..."
setenv bootargs "console=${console} root=/dev/nfs rw rootfstype=nfs ip=dhcp nfsroot=192.168.1.115:/BigDisk/ti-sdk/rootfs"
printevn bootargs
tftp ${loadaddr} zImage
tftp ${fdtaddr} ${fdtfile}
bootz ${loadaddr} - ${fdtaddr}
nick@nick-KGP-M-E-D16:/BigDisk/ti-sdk/boot$
然后使用命令编译mkimage -A arm -O linux -T script -C none -n boot.scr -d boot.scr boot.scr.uimg
这个是这两天唯一的有意义的事情。使用buildroot也遇到了问题,不能理解的是为何内核编译产生了out of sync的问题,看样子我不能使用任何的target package,所以早晨的时候我在想与其在文件系统的制作上花这么多精力还不如直接自己编译package,或者交叉或者beaglebone起来后直 接编译?看来又要回到yocto了?
要么先看看qt5的代码的编译

八月四日当前只有等待等待

但是qt依赖libx11.在万般无奈之下发现还是寻求linuxfromscratch的帮助,也许最终这个是你的唯一选择?但是它需要libxcb,而它有需要xcb-proto 和xau,编译安装了xcb-proto之后还要手动拷贝xcb-proto.pc到/usr/lib/pkgconfig
我的bbb的/etc/resolv.conf是空白,所以没有办法访问Internet,加上了我的router的地址作为dns解析就好了。
root@beaglebone:/usr/src/xcb/proto# cat /etc/resolv.conf
nameserver 192.168.1.1

八月六日当前只有等待等待

使用beaglebone black作native的编译太慢了,一昼夜也没有编完QT,看样子只有用主机作交叉编译才是可行的。下载一个TI的关于pru的白皮书,插图很好看。昨天我对于为什么要使用qt又产生了质疑,我究竟目的是什么?仅仅是TI的demo是使用qt的原因吗?这里TI的graphic sdk的下载地 址。这个是am335x的开机参数,应该是使用graphic sdk的情况? setenv bootargs 'console=ttyO0,115200n8 root=/dev/nfs nfsroot=<nfshostipaddress>:<rootpath>,nolock rw mem=256M ip=dhcp earlyprintk=serial vram=50M'
TI有很多的training。这个才是sdk下载的入口,好多资料啊。保存一个graphic sdk的版本。这个是ti 的sdk本地保存的。很多都是废柴,因为是32位的平台我无法运行,也不太感兴趣,这个lab也许才有用。

八月八日当前只有等待等待

同样的错误我又忘记了,需要设定内核的ROOT_NFS 的选项否则就会有Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,255),我一连两天一直以为是内核于文件系统不一致害得我把yocto的状态也要删掉。
这个帖子关于xcb的遗失是 这样解决的,我尝试增加IMAGE_INSTALL_append = " qtbase qtbase-plugins qt3d qtconnectivity qtmultimedia qtmultimedia-plugins qtserialport qtsvg qtx11extras"在local.conf里,并添加DISTRO_FEATURES_append = " x11 xcb"。
qt运行期需要设定QT_PLUGIN_PATH用来指向libqxcb.so吗?
我已经来不及去验证这个错误的原因了:内核设置了root_nfs然后启动失败,我认为是我把nfs的client都设定成了module,然后文件系统没有把module也解压缩到文件系统。后来我索性把所有的nfs-client都编译进了内核。应该是这样子的把。
期间eclipse无法正常运行,我认为是内存不足的缘故,这个样子好像还行吧,是eclipse.ini的设置-Xms和-Xmx的设置似乎不能超过4096M:
-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.200.v20150204-1316
-product
org.eclipse.epp.package.cpp.product
--launcher.defaultAction
openFile
-clean -showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
8192M
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.7
-XX:MaxPermSize=8192m
-Xms4096m
-Xmx4096m
我现在已经又要决定放弃buildroot的途径,似乎yocto是在解决buildroot的短板,并且之前在bbb的native编译qt5居然用了两天两夜的时间,所以,必须使用交叉编译。

八月九日当前只有等待等待

当前的任务究竟是什么?两条腿走路,一个是yocto的配置,我加入了xserver-common作为Installed package,但是出现了所谓的x11vnc的redundant rpath的错误,这个我找到了讨论的email,似乎是狠心的而且有人在fix,但是我不确定,因为我的版本似乎也不对,还是先更新再说。另一个就是究竟我要采用什么graphic stack,这个问题不是我一个人在问,这一点让我感到心安,这的确是一个很好的学习过程,这里有一本非常非常好的书,这一次我一定要真的真的读一下。要保证。
在/etc/resolv.conf里设置不是根本的办法,需要在/etc/network/interfaces 里设置dns-nameservers 192.168.1.1
这个值得阅读。这个总结的很好

八月十一日当前只有等待等待

yocto中的内核配置正确的做法是在recipe-kernel里的defconfig里作修改,否则你强行作bitbake linux-stable -c menuconfig会导致随后编译image爆出内核被taint因为forced run的警告,虽说是警告实际是错误,因为我通过修改内核配置和实际的文件系统就是不一致了,至少我遇到的问题的一部分是这个造成的,v4l2的模块始终 无法加载,uvcvideo总是抱怨说v4l2的各个symbol都是unknonwn,我猜想这个是在制作文件系统时候拿的内核模块和我实际编译的不 同,虽然我强制把内核编译时候的modules解压缩到文件系统实际的版本是不同的,我的理解是制作文件系统时候模块是自动被放入了,如果这个都做不到那 么yocto就太无能了,我应该是不用手动解压缩的。所以从这一点也侧面应证了我之前的错误,因为要使用nfs文件系统所以内核必须要有 nfsclient的模块而且不能是M的,当然nfs-rootfilesystem也必须要的。于是我就应该把这个加入defconfig里。
看webcam插入后内核事件我猜想所谓的uvc是建立在ehci-pci,就是用usb host来模拟或者说实现pci协议的过程,在内核配置中这个需要USB_EHCI_PCI,这个依赖于PCI的配置,而默认的bbb居然没有选pci,所以。。。无语。

八月十二日当前只有等待等待

v4l2压根是内核的驱动,而且使用ioctl所以无需任何user space的库支持就可以,所以我想去除掉当初加上的libv4l2。

八月十三日当前只有等待等待

已 经很接近解决了,首先,v4l2的支持已经有了,就是说uvc的webcam可以建立v4l2的device文件,现在我可以取出capture的图像 data,我现在需要的是使用framebuffer来显示图像,framebuffer默认支持的color是rgb565,我能否让它支持 webcam默认的yuv420呢?这里说的是怎样设定format,本地保存一份
To select a format, applications set the grayscale field to the desired FOURCC.
For YUV formats, they should also select the appropriate colorspace by setting
the colorspace field to one of the colorspaces listed in linux/videodev2.h and
documented in Documentation/DocBook/v4l/colorspaces.xml.

The red, green, blue and transp fields are not used with the FOURCC-based API.
For forward compatibility reasons applications must zero those fields, and
drivers must ignore them. Values other than 0 may get a meaning in future
extensions.

八月十四日当前只有等待等待

遇到了意外,v4l2的DQBUF挂机在那里,难道这个是driver的问题?内核版本4.4比我的主机都高,似乎不太可能??这个讲义很好看

八月十六日当前只有等待等待

这看来是完全不可逾越的障碍,肯定是内核驱动的问题?v4l2的device完全不可用?我即便使用简单的read也被block,加载mmap或者userptr的qbuf都返回状态不是正常的,所以dqbuf就一直block,我花了一些时间来阅读linuxtv的关于v4l2的文档,依然没有头绪,我越来越倾向于这个是新版4.4内核驱动不兼容老的uvc设备的问题。现在怎么办呢?最简单的也许是尝试3.x的内核或者先实验一下4.4以前的4.x内核。对于dts文件我依然没有时间研究,这个需要专门的学习,以后再说吧。


八月十七日当前只有等待等待

原本十分清晰的路线完全混乱了,完全不知道这是否是内核4.x的问题,怀疑是,可是怎么证明呢?注意到大多数的内核似乎针对bbb都是比较老的,应该是有些 兼容性的问题吧?但是这个混乱中有一点是明确的,而且是有进步意义的就是明确了yocto的方向是唯一正确的方向,和buildroot比较起来有着非常 大的优势,现在的主要目标转变为学习yocto的问题了。这是一个编译内核的教程

八月十八当前只有等待等待

只有在/usr/share/applications/eclipse.desktop下创建的才会被unity的launcher接受。yocto的内核修改教程的recipes,这个是配合教程文件的,他们是对应比较早期的yocto版本的,其实还是适合老版本的linux,比如python2.7。

八月二十日当前只有等待等待

完全的迷茫。问题在于目前的yocto都是使用最新内核,我需要使用较早的Yocto版本,这个本身就是我所想要避免的。
一个验证的途径就是使用现有的image来看看是否真的老内核没有这个问题,我的记忆模糊了,过程是这样子的:
sudo fdisk -l bone-debian-7.9-lxde-4gb-armhf-2015-11-12-4gb.img
                                            Device Boot      Start         End      Blocks   Id  System
bone-debian-7.9-lxde-4gb-armhf-2015-11-12-4gb.img1   *        2048      198655       98304    e  W95 FAT16 (LBA)
bone-debian-7.9-lxde-4gb-armhf-2015-11-12-4gb.img2          198656     6963199     3382272   83  Linux
这里我的记忆真糟糕,偏移是block,不是bytes,所以要mount 第二个分区是198656*512=101711872
sudo mount -o loop,offset=101711872 bone-debian-7.9-lxde-4gb-armhf-2015-11-12-4gb.img /mnt/rootfs
因为这些镜像都是使用initrd,我不想再改我的启动脚本,所以,就用microsd来启动:
sudo dd if=
bone-debian-7.9-lxde-4gb-armhf-2015-11-12-4gb.img of=/dev/sdh bs=8M
我现在已经忘记了究竟是我在主机上的boot.scr.uimg在起作用还是emmc上的uEnv.txt在起作用,完全想不起来了。似乎是跟我编译的u-boot版本有关系,我使用的是jumpnow的版本。记忆力啊。
也许真的是硬件的问题

八月二十三日当前只有等待等待

只有从头学习yocto一条路,令人欣慰的是angstrom也是一个yocto工程。
怎么说呢?原本你有一条康庄大道可是你不愿意走寻常路,于是走上了羊肠小道,不是不可以,只是你还没有到火候。使用jumpnow的bsp固然不错,此人 有很多的小革新值得我慢慢学习。可是poky原本已经有现成的工具作我所需要的及其简单的工作。比如:下载了poky-krogoth,你可以修改你的 conf,我发现最适合我的是把download/sstate/tmp都设成隐含目录这样子eclipse就忽略他们了。然后使用yocto-bsp create nick-bsp arm -o $PWD/../
然后再使用yocto-kernel
我买了logitech c920 HD为了验证究竟是否是硬件的问题,在3.18内核下,它使用userpointer是可以正常输出的,可是4.4内核就crash了,而3.18内核 c310就不行总是报说select timeout。更可能的是硬件和内核都有问题,驱动的问题也许往往是双方面的吧?

八月二十四日当前只有等待等待

我的bb没有如之前的有效,v4l-dev没有部署,但这个还不是重点,我发现我需要学习dts,这时候买的那本书体现了他的价值,这个是gpio的入门步骤,非常的有价值。

八月二十五日当前只有等待等待

非常好的yocto概述,图文并茂,属于入门介绍。

八月二十七日当前只有等待等待

犯了无数多的图形方面的基本的错误:1.framebuf只支持rgb565的格式,那么从rgb888==>rgb565应该怎样的呢?这个是以 前闭着眼睛都不会搞错的啊:unsigned short r=0,g=0,b=0; r=(rgb[0] >>3) <<11; g=(rgb[1]>>2)<<5;b=(rgb[2]>>3) ; rgb565[0]=r|g|b;
我一直无法发现这个错误,结果为了debug就打算用bmp来输入去写framebuffer来检验,结果bmp格式读的时候又发生了错误,因为我找不到 一个官方的库来读bmp,结果就google了一个自定义的结构,这个我以前也在windows下看过微软的定义不会错的,所以就抄过来没有在意,结果除 了什么错误呢?
typedef struct {
   unsigned short int type;                 /* Magic identifier            */
   unsigned int size;                       /* File size in bytes          */
   unsigned short int reserved1, reserved2;
   unsigned int offset;                     /* Offset to image data, bytes */
} HEADER;

typedef struct {
   unsigned int size;               /* Header size in bytes      */
   int width,height;                /* Width and height of image */
   unsigned short int planes;       /* Number of colour planes   */
   unsigned short int bits;         /* Bits per pixel            */
   unsigned int compression;        /* Compression type          */
   unsigned int imagesize;          /* Image size in bytes       */
   int xresolution,yresolution;     /* Pixels per meter          */
   unsigned int ncolours;           /* Number of colours         */
   unsigned int importantcolours;   /* Important colours         */
} INFOHEADER;
我很久没有写代码才会忘记的:结构需要alignment,我忘记了这个:
#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */
。。。
#pragma pack(pop)   /* restore original alignment from stack */
3. arm上的浮点运算应该是比较慢的所以我找到了避免使用浮点的yuv转rgb的例子:
#define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)

// RGB -> YUV
#define RGB2Y(R, G, B) CLIP(( (  66 * (R) + 129 * (G) +  25 * (B) + 128) >> 8) +  16)
#define RGB2U(R, G, B) CLIP(( ( -38 * (R) -  74 * (G) + 112 * (B) + 128) >> 8) + 128)
#define RGB2V(R, G, B) CLIP(( ( 112 * (R) -  94 * (G) -  18 * (B) + 128) >> 8) + 128)

// YUV -> RGB
#define C(Y) ( (Y) - 16  )
#define D(U) ( (U) - 128 )
#define E(V) ( (V) - 128 )

#define YUV2R(Y, U, V) CLIP(( 298 * C(Y)              + 409 * E(V) + 128) >> 8)
#define YUV2G(Y, U, V) CLIP(( 298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8)
#define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U)              + 128) >> 8)

// RGB -> YCbCr
#define CRGB2Y(R, G, B) CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16)
#define CRGB2Cb(R, G, B) CLIP((36962 * (B - CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16) ) >> 16) + 128)
#define CRGB2Cr(R, G, B) CLIP((46727 * (R - CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16) ) >> 16) + 128)

// YCbCr -> RGB
#define CYCbCr2R(Y, Cb, Cr) CLIP( Y + ( 91881 * Cr >> 16 ) - 179 )
#define CYCbCr2G(Y, Cb, Cr) CLIP( Y - (( 22544 * Cb + 46793 * Cr ) >> 16) + 135)
#define CYCbCr2B(Y, Cb, Cr) CLIP( Y + (116129 * Cb >> 16 ) - 226 )
然后每次读两个pixel来转换yuv:
                int u = src[1];
                int v = src[3];
                int u1 = (((u - 128) << 7) +  (u - 128)) >> 6;
                int rg = (((u - 128) << 1) +  (u - 128) +
                          ((v - 128) << 2) + ((v - 128)  << 1)) >> 3;
                int v1 = (((v - 128) << 1) +  (v - 128)) >> 1;
                unsigned short r = 0, g = 0, b = 0;
                r = CLIP(src[0] + v1) >> 3;    //to convert to rgb565, chop it
                g = CLIP(src[0] - rg) >> 2;     
//to convert to rgb565
                b = CLIP(src[0] + u1) >> 3;    //to convert to rgb565

                dst[0] = (r<<11) | (g<<5) | b;
                r = CLIP(src[2] + v1) >>3;
                g = CLIP(src[2] - rg) >>2;
                b = CLIP(src[2] + u1) >>3;
                dst[1] = (r<<11) | (g<<5) | b;
这个部分我没有什么错,或者说错误就是rgb565和bmp一样的没有缩减从8bit到5,6bit的错,但是当我拷贝640x480到 1920x1080的时候,padding居然算错了,source是uvc camera扑捉的yuv422的640x480,而dest是framebuffer的rgb565格式的
1920x1080,那么我的padding应该是每行是1920-480,我居然糊涂到了1920,导致出现了大约三个模糊的影像。
5.结果就是使用内核3.18虽然uvc的camera的v4l2的capture可以,但是hdmi非常的flickering眼睛都要花了,看来是 hdmi的显示驱动有问题,4.4之类的新内核没有这个问题,但是怎么解决camera的问题呢?而且在3.18下,图形显示相当的慢,这个看来不是新旧 内核的问题,而是算法的问题,我依然是使用capture的userpointer作mmap的来的一个capture的内存,然后直接写 framebuffer显存,没有更快的了,瓶颈就在于两者格式的差别需要转换,而这个是想当的慢的,可是camera只有yuv422和h264,而 framebuffer也只有rgb565的格式,我有什么好办法呢?

八月三十日当前只有等待等待

我想尝试利用neon的SIMD的特性来提高效率,可是意识到这个似乎对于图形的single plane不适用,因为数据要是packed就可以了,可是rgb或者yuv都是混在一起而不是rgb各自在一个数组里。不过还是写下使用neon的方法,没有检验过。
g++ -march=armv7-a -mtune=cortex-a8 -mfpu=neon -ftree-vectorize -ffast-math -mfloat-abi=hard
不过怎样enable neon呢?那些汇编似乎不行,运行期报错说Illegal instruction。我就此放弃了。我下载过am335x的TRM吗?

八月三十一日当前只有等待等待

ti的wiki的解说不是很明白究竟显示格式不能改变是否是fbdev的问题, 还是tilcdc的因素?我决定使用ti的kernel来实验一下,git://git.ti.com/ti-linux-kernel/ti- linux-kernel.git;branch=ti-linux-4.4.y 本来想使用本地的git但是折腾了一下不明所以然,还是用ti的server的吧,现在要折腾的东西太多了。重新读这个小朋友的心得, 依然不是很确定我需要改变多少来使用drm/kms,这个看起来比fbdev复杂很多,是否效率更高呢?我现在有一个模糊的概念,直接访问显存的 framebuffer的fbdev是否就是最快的呢?所谓直接访问应该是对应用程序的一个假象,实际上也许还是有内部的dma负责把内存内容在系统 user可以访问的内存和显示设备之间进行来回拷贝,这个理解不知道对不对?也许至少对于很多嵌入式设备应该是这样子把?那么如果这个假设是正确的那么 drm/kms之类的dri应该并不会比fbdev慢,因为这个完全取决于实际显示设备支持哪种驱动的方式,也就是说如果我的fbdev并不是真的让我直 接访问的显存,那么使用drm也许不是什么坏事。回过头来看这个总结,对于embedded multimedia application开发是一个很好的入门的巡礼,让你有一个大方向。所以我的需求是读linux graphic driver的讲解

九月一日当前只有等待等待

libdrm 是一个包,它包含了所谓的modetest这个小小的测试命令,所以,在yocto里去增加image输出的包libdrm-tests。当然,为了使用 libdrm你需要增加libdrm-dev的包。不过让我困惑的是有两个drm.h分别在drm和libdrm下而且不同的内容。看来需要学习drm- kms因为似乎现在的显卡驱动都倾向于支持这个而不是fbdev。另一个不解的问题就是ti说tilcdc的第二版支持rgb888可是我似乎没办法,也 许我使用的还是不被支持的fbdev的缘故?直接使用ti的内核无法启动,这个应该是预料之中的,因为在compatible-machine里就没有 beaglebone,我硬性添加自然不会成功的。
运行modetest似乎是支持rgb888的,但是我现在还不知道怎样使用drm/kms编程。把这段时间的实验的代码保存一下,都很垃圾,全都是从sample code里直接改一改做实验的,懒得整理。

九月二日当前只有等待等待

我读我今年的日记非常的惊讶我每天都几乎再重开一个全新的领域,所谓浅尝辄止,走马观花,兴趣不断的游弋,看来还是缺乏恒心和毅力的表现。当然,我确实也学到了很多,而且我现在的记忆力非常的差常常一两个月以前的事情完全没有印象,需要一点一点的回忆才行。。。
我想总结一下我目前的状况:
1.内核编译和尝试的过程应该要停止了,否则是一个永无止境的过程,对于我来说使用linux-stable 4.4是足够好的了。好像也是目前的lts,驱动代码足够新了。听说dts的引进是3.8?所以,我觉得目前是一个很好的阶段,不大会有很大的飞跃。
2.yocto的探索也差不多了,其实它最大的优点是给你一个working的全套image,我猜想最有用的部分是你连toolchain都没有的 absolutely from scratch的时候,一旦稳定下来,实际上你自己用toolchain编译单独的包应该更容易,(不过dependency谁来解决?比如你更换了 package A的版本如果还有一大堆的packages depend on A,你怎么办?你一个一个编译吗?所以这个时候还是Yocto来的好用。)另外调试内核配置等等不算太麻犯基本上使用Yocto和手动编译差不多。不过我 始终心存疑惑的是:如果你改变了内核版本,那么你的文件系统是否应该重新编译?这一点似乎yocto是正确的,就是基本上每次都需要重新编译文件系统。只 不过到具体的包是否有必要重新编译就是一个大大的问号。究竟内核的头文件部分有多大的改变导致了一些library需要重新编译呢?yocto有作这个 dependency的检查吧?总之,频繁切换内核版本的过程要停下来了。
3.webcam使用Usb也许是效率上有些损失,但是我觉得更大的滞后来自于图像处理部分,目前我鉴于输出的Hdmi使用的是rgb565需要从 yuv422进行转换非常多的工作,至少如果tilcdc按照ti的wiki说的能够支持rgb888就能减少一部分工作,这个是第一步能够做到的,我目 前使用的是/dev/fb0是直接使用fbdev,我目前认为这不是官方正式支持的驱动,官方的drm-kms应该使用的是 /dev/dri/card0,那么当前的工作就是实验这个驱动产生的framebuffer,(我目前的认识认为这个framebuffer是一个虚拟 的,与fbdev相比也许要慢一些,但是回过头来想,所有的framebuffer都不一定是显卡的真正的物理内存,或者通过mmio,或者通过dma等 等,framebuffer并不代表你就是“真正”的直接访问显卡内存,这个取决于显卡驱动的实现,所以,也许drm/kms的framebuffer要 比一个糟糕的fbdev实现的framebuffer来的快?)
4.目前我对于linux graphic driver部分的认识还是太少,对于2d的部分也许使用svga就足够了?我还是不明白svga直接访问内存的方法是否就比fbdev的方法来的更快? 还是说这个都是显卡的不同驱动的不同的实现?那么究竟能否直接使用显卡的native的驱动来直接访问呢?我看到的一些slides说x-server就 有可能直接绕过驱动,比如uvesa等等的直接访问显卡的驱动,也许我可以学习显卡的工作机制。
5.以前我买的那个sensor看起来很难集成进来,它有一个输出的ribon看上去是很多pin,那么beaglebone有什么接口能够同时接受这么多的信号呢?这一些是我的盲点,是我一直渴望学习的部分,慢慢来吧。
这个linux graphics demythified看起来不错,linuxgraphicdrivers是一个大的high-level的picture,而后可以慢慢深入。这个是今天阅读的作业。我准备手动同步到公司去阅读。

九月四日当前只有等待等待

突然看到手册中关于hdmi的 表述,虽然以前浏览过几次,但是只有现在才明白为什么是rgb565的模式。不过我还是将信将疑,因为这个pin难道不是为了lcd cape准备的吗?我使用的是Hdmi的输出,应该是所谓的raster mode。不过回过头来想应该是hdmi的接口是要作成一致的,也就是说DA19988引出的就是rgb565这个是无法改变的信号源。

九月五日当前只有等待等待

这个是beaglebone和bbb是不同的,对于beaglebone家族我有些混乱,这个是TI的总结很清晰了。bb的最新的手册下载网址是这里。这个很可能已经过时了,是radiumboards.com的一个camera cape

九月九日当前只有等待等待

这个是很好的图片,解释linux graphic system大模样amd/ati的驱动

九月十日当前只有等待等待

没时间看neon,存一个。发现所谓的libdrm别有隐情,一个是原装的所谓的libdrm,还有另外一个,因为一个在/usr/include/drm另一个在/usr/include/libdrm下面。当然使用的都是libdrm.so这个比较的奇怪。

九月十二日当前只有等待等待

茫茫然的实验,似乎只明白了一些,还是处于茫然中。使用drm似乎还是有很多疑惑,究竟drm和libdrm下的头文件为什么是不同的,原本认为很明显的是libdrm是drm的一个包装,可是。。。看libdrm的代码用到libpciaccess,而它有用到libpci,然后就在编译libpci/pciutils时候遇到了一些疑惑,linker有一个version script, 这个在工作中被hnas的人提到过用来对付多版本的shared library,只是当时不解,现在依然有疑问。我现在已经完全偏离了既定的目标,甚至不知道什么目标了。使用drm你可以创建你所需要的rgb888的 framebuffer,但是性能上并不见的有什么强的,似乎这个是drm/encoder的能力,总是的有人来做colorspace的转换,这究竟有 什么意义呢?

九月十八日当前只有等待等待

有些迷茫,有些彷徨,感觉最容易的还是从写module做起,总要有一个入口和入手的途径。

九月二十日当前只有等待等待

比起两三年前读kernel module/device driver,现在要容易的多,当然我以前也没有读完过,每次都是从头读,不过学习就是这种过程,不然为什么要学而时习之,实际上没有人能够一次就明白所 有的部分,回过头来看增长更多。我作helloworld结果把cleanup_module名字写成了clean_module结果无法卸载 module,看来只有重启之后才行,不过no worry我换一个module 名字就是了,在Makefile里虚拟一个Module名字:
obj-m += fake.o
fake-objs := fake.o
这样子你的module的名字就变成了fake.ko和原来的并存好像是alias一样。

九月二十三日当前只有等待等待

浏 览了一下arduino,我很快的评估决定pass,这个面向的是初学者,比如中学生,也许容易上手,便宜。但是最要命的是为了这个目的要使用一套专门的 软件和ide来工作,也许你可以绕过这些直接使用芯片厂商的工具来作,但是最核心的问题是它不是用linux内核,使用厂商自己的os,这个是show- stopper,我觉得目前我还是使用bbb为好因为至少主流内核是支持的,这个是关键。

九月二十四日当前只有等待等待

买了一块saa7160(rev3)的hdmi接口的tv capture card,linux内核不支持,这个让我有些诧异,看内核驱动的历史这里好像主流把这个系列剔除了。这里是saa7160的说明书

九月二十五日当前只有等待等待

内核代码的basic的basic的tips: 头文件不要使用include,这样应该是防止嵌套的include,加快编译速度,也可以让代码更加的干净,因为都是在.c文件里include,所 以,其中的顺序很重要,也就是说include的要从linux/xxx.h的系统头文件开始,这些是在内核的Include目录下的,作为其他开发者可 以使用的,而你的自己定义的头文件里有很多会引用到系统定义的部分,所以,要把系统的头文件放在前面。
为了不让linux kernel的localversion末尾添加+,touch .scmversion
1. ubuntu-trusty的内核代码:git clone git://kernel.ubuntu.com/ubuntu/ubuntu-trusty.git
2. 从ubuntu内核的tag创建我当前内核的版本: git checkout Ubuntu-lts-3.16.0-67.87_14.04.1 -b nick-saa716x
3. 从https://github.com/ljalves/linux_media.git下载了linux-media的非主流内核,这个可以作为一个参考明白saa716x模块是怎样编译的,不过这个版本已经很老了缺乏维护,移植到新版主流内核工作量较大。所以,选择以下的版本。
4. hg clone https://bitbucket.org/powARman/v4l-dvb-saa716x这 里的模块代码比3要新而且支持新版内核。不过需要一些修正,这里让我比较困惑的是,维护者似乎没有遵循linux-media的传统,违背了一些基本的原 则,比如把saa716x模块放在common而不是作为pci的一个小模块是否有意义,这一点我还没有理解。不过头文件不应该使用相对目录是否是一个传 统约定呢?
5.编译内核时候发现内核版本不符合: make kernelversion,我不明白为什么从tag 3.16.087出来的版本确实3.16.7,只好手动修改Makefile的版本,但是make kernelrelease是动态产生的,会添加+在尾巴,需要创建一个空的.scmversion: touch .scmversion。但是单独编译模块是不对的,一定要完全编译内核一次否则会遇到错误:no symbol version for lay_out.
6.不敢立刻安装模块,于是单单使用insmod会遇到unknown symbol的错误,因为modules之间有依赖关系。后来版本确定一致后,sudo make modules_install,然后就可以使用modprobe来安装模块了。

九月二十六日当前只有等待等待

还是看不太懂pcie的原理

九月二十七日当前只有等待等待

这个解释pci的ppt很好,让我明白了pci bridge,因为你在lspci里看到的bus:device.function是在pci domain下的。

九月二十八日当前只有等待等待

<The C++ Programming Language> by Bjarne Stroustrup.
最基本的pci常识学起。

十月一日当前只有等待等待

我想了一个办法,比较saa7146saa7160的 异同,来学习saa7160究竟需要做什么,因为kernel里是有saa7146的代码,我的猜想是也许芯片公司的开发也是基于之前的架构一步一步扩展 的,说不定saa7160的底子就是saa7146,虽然前者是pcie后者是pci但是其中图形处理部分说不定是一样的或者相似的。这个只是我的猜想, 只有看过才知道。

十月十一日当前只有等待等待

为了验证一个简单的东西,我居然花了一个多小时在编译我的测试jsoncpp,最后才发现需要使用c++11,当然这个是1.x.y版本,如果是0.x.y就不需要了,这个在git主页写的清清楚楚,我没看。

十月十三日当前只有等待等待

我以为我发现了新的问题,可是到公司发现好像代码不一样,难道是K已经修正了这个缺陷?

十月十六日当前只有等待等待

下载了英雄无敌2的linux重做版本,相当的不错!引擎框架齐全,就只有ai是比较简单,而这个正是我梦寐以求的,因为heroes3说老实话有些过于复杂了,游戏ai做的也是有些登峰造极了。而这个2实际上还是可以作为实践的工具的,首先,我就修正了一个小的不能再小的bug, 就是随机事件导致资源为负数的问题,其实,这个也许原版也是允许的吧?所以,我不确定这个是bug。但是我不喜欢资源为负数。然后,我又自以为发现了另一 个著名的bug,就是投降的英雄行动力恢复这样导致你可以几乎无限次招募英雄带一个凤凰使用伤害法术不停地对敌人攻击,只要你的钱足够多,每次凤凰才 300金子实在是便宜,我自以为找到bug要修正,看代码才发现作者把这个设为了一个选项,是可以在new game的config菜单里设置的:HEROES_REMEMBER_POINTS_RETREAT,这让我比较的尴尬,作者比我高的不是一点两点,我 要好好的学习一下。然后,又以为发现了另一个bug,就是lich在远程攻击时候,不分敌我伤害所有爆炸范围的生物,我印象中heroes3中, undead是可以豁免的,查阅网上的说明看来heroes2是有区别的,不论是死是活不分敌我都杀杀杀。看来我对于heroes2的记忆已经很淡忘了, 作者是对的,不过我debug找到代码的本来意思也是对自己的一点点安慰,毕竟我是有能力修改程序的,只是游戏设置理解不对。我又添加了windows的heroes2gold,原因是Linux的引擎是不包含data和map下的资源文件的,我自己添加了他们,详见作者的readme。

十月二十日当前只有等待等待

我的使用S3的dumb git server的做法可能是有问题,我之前一直没有发现也许是因为一些简单的project,我自己仅仅就是一个类似于github的搬运工,git init 一下没有任何提交的历史吧?总之现象是git clone从s3的时候总是抱怨有什么object找不到,于是我就写了一个简单的脚本来“clone"我的初始化的git repo,这个就是完全拷贝,然后载删除非git控制的文件,如果这个还有问题那肯定就没有天理了。

十月二十二日当前只有等待等待

今天早上搞明白了一件事,网上有人评论说2010年中国GDP首次超过日本,然后到2015年中国GDP是日本的2.4倍,这让我很吃惊,就是如果日本原地踏步。。。

十月二十七日当前只有等待等待

应该说fheroes2已经做的非常棒了,操作层面几乎是99%忠实原作,但是ai部分实在不能苟同,但是这个是完全可以理解的,所有游戏的ai引擎都是独 立的一个巨大的project,能写到现在这个水平已经不简单了,我自以为练剑十数载,可是经常发现自己还像一个初学乍练的小学徒,比如作者的debug 宏我就没看懂,这个是几乎所有大型项目的log输出的通用做法,我实在是自惭,跟踪了好久才醒悟输出ai的trace需要自己添加命令行,或者在cfg文 件里设定,debug不仅仅是level,还包含了模块,所以,需要这样来做:./fheroes2 -d 798 2>/tmp/ai.log 我想是否应该参考一下wesnoth的ai模块做法呢?

十月三十一日当前只有等待等待

发现了一些bug,这个算是尝试吧,就是计算最高价值目标的时候也要考虑攻击后敌人反击造成的损失,所谓杀敌一千自损八百,鼓励ai围攻。发现的bug是黑龙之类的寻找两格杀伤位置的算法有错,正在尝试改错中,算法比较复杂麻烦。

十一月三日当前只有等待等待

修订了黑龙的双格杀伤位置计算, 下一步是在所有的位置中选择反击最少的攻击位置。但是,AI目前的计算属于比较简单,即一开始确定攻击目标狠命向前冲,所以一旦到达就是短兵相接不再选 择。所以,我要写一个所有能够到达的位置的函数,原来代码可能是有的,我看到一个A*的寻路算法的函数,但是还没看懂,不知道它是如何和兵种速度结合的。 这个等回来再说吧。我一开始在playstore上看到vcmi以为有了新的版本,后来去vcmi的官网看是一年多前的,heroes3比heroes2 复杂很多倍,所以,作为AI来说还是用这个fheroes2来作试验场比较好。我的计划是至少arena能够实现dfs或者bfs之类的有限深度搜索然后 每轮将实际情况与计划做比较然后再把之前的深度相应增加一层到达目标深度,也就是说每轮都是一轮深度,只有开局是n层。每轮为了减少内存删除没有用到的选 择支。

十一月十七日当前只有等待等待

这个bug花了我几乎两个星期来修订,首先要理解heroes2里面的六角格子,unit都有一个所谓的基本方向,就是说敌人在左边,你的黑龙朝右边去喷火 那肯定是很尴尬的。纯粹的左右方向攻击没有那么复杂,但是对于斜角是否能够真的符合左右呢?这里的判断只能是大概,其实玩家也没有苛求,但是问题就在于攻 击动画尽可能贴近实际和损害算法之间是有矛盾的,在我算定了两格攻击的时候是明确黑龙的头的位置,敌人也是确定的,这里的插曲是我花了一些时间来理解作者 攻击位置价值的算法,就是每个位置的攻击价值等于伤害周围敌人的最大值,这其实是一个捷径的粗略算法,作者也许为了简化寻路,使用A*寻路需要目的地吧。 但是两格攻击和九头蛇的全方向攻击就要加成所有伤害,不过大多数情况下这个位置的所谓质量分数是可以保证敌人目标的正确选择,所以,我最后跟踪代码很久决 定最简单的改法就是加一个攻击方向的指示,这个是在双格攻击强制在动画需求逼真方向的时候要求严格使用我指示的方向从头部喷火。

十一月十九日当前只有等待等待

五年以前我一直以为中美对抗要以中日开战作为必经之路,现在突然眼前敞亮发现不是的,台湾问题必须要首先解决。首先,这个是内政师出有名,不同于中日对垒, 而且美日韩有军事同盟协防的责任,对于台湾美国只有售台武器的利益,所以,武力统一台湾更加顺畅。对于日本海空军切不可小视轻言战端。其次,解决台湾问题 不仅仅是小试牛刀杀鸡儆猴,更是反守为攻以逸待劳,拔出美日同盟的眼线也是敲山震虎的威慑,既不可轻开战端也不应妄言不战。时间在中国军队一边,美国等不 得,中国急不得,解决南海与台湾海峡即使海上生命线的保障也是日本韩国生命线的控制,是突破第一岛链的必然,也是敲打港澳新加坡的必须,武力震慑台湾不求 武力急统,但也不可妄议不战的谬论,其中尺度拿捏随机应变存乎一心。所以在2020年以前需要做好武力镇统台湾的军事准备。

十一月二十一日当前只有等待等待

找到了一个homm2的详细说明,我忘了两次攻击的弓箭手是否近战也能如此。准备修改对敌单元评估算法不是杀死敌人生命值多少而是消灭敌人潜在攻击能力多少。

十一月二十七日当前只有等待等待

对于homm2的ai的改进让人有些茫然,因为要改的部分太多,不如重新来过,所以,我想看看homm3也就是vcmi的做法。编译的时候遇到的错误主要是 ffmpeg的链接错误,一个是版本要足够新,一个是要用动态库,或者enable-pic,总之我感觉这个是一个快速的解决问题的办法。-- enable-shared

十一月二十八日当前只有等待等待

vcmi非常的费解,大量的使用c++11的新语法放我有些迷茫,一个水车的金币每次都是500的小问题我改了两次都没有改好,似乎网络上也有人抱怨。AI似乎也还在起步阶段,那么是不是应该回归homm2呢?
在工作中混合链接静态库和动态库的时候,对于一些老版本的gcc需要使用特殊的linker flag,原理大约是Wl,-Bstatic或者Wl,-Bdynamic之后就期待这都是一类的静态或者动态库,如果混合的话就无所适从了,所以,如果 你大部分都是动态库,偶尔穿插一个的话,比如boost_system,那么需要这样子:-Wl,-Bstatic -lboost_system -Wl,-Bdynamic  后面的dynamic表示其后都是动态库,因为即便你的链接结束了但是最后gcc还有很多的自带的动态库要加上去。
使用多个nohup的命令时候可以使用sh -c "cmd1 && cmd2",所以这样子:nohup sh –c “first && second” &
boost的编译有些头疼,在boostrap的时候可以指定要编译哪一个库否则太慢了,比如只想编译boost_system的话--with- libraries=system,同时你可以指定仅仅编译静态库:link=static,所以完整的是,注意一定要pic如果编译静态库的话,因为十 有八九你是要编译到动态库里的。
sh ./bootstrap.sh --prefix=${BOOST_DIR} --without-icu --with-libraries=system    
./b2 link=static cxxflags=-fPIC install --prefix=${BOOST_DIR}
交叉编译更罗嗦,要写进一个配置文件,我当初搞错了目录伤了脑筋,然后你在toolset里指定你的toolchain,甚至是版本号:
echo "using gcc : 4.9 : x86_64-bluearc-linux-gnu-g++ ;" > tools/build/v2/user-config.jam
./b2 link=static toolset=gcc cxxflags=-fPIC install --prefix=${BOOST_DIR}
在使用sed替换的时候,为了防止反复替换需要使用搜索字串的结束符"$",这样子的话你就不会多次替换了:比如原文是export CC就结束了,要替换成export CC=x86_64-bluearc-linux-gnu-gcc,可是替换后的字串是原文的超集所以不加上结束符会被再次替换的:以下是编译poco的交叉编译的设置,很烦人的做法。
sed -i "s|export CC=$|export CC=x86_64-bluearc-linux-gnu-gcc|g" build/rules/global
sed -i "s|export CXX=$|export CXX=x86_64-bluearc-linux-gnu-g++|g" build/rules/global
sed -i "s|export LINK=$|export LINK=x86_64-bluearc-linux-gnu-ld|g" build/rules/global
打补丁以前都是依赖于svn,在没有svn的时候单单使用diff需要特别注意这样子: diff -Naur oldfile newfile  > mypatch.patch 然后你最好删除newfile否则你原地打补丁会有错patch -p0 < mypatch.patch
为了防止多次打补丁最好使用一个文件来标示:
if [[ ! -f ${APPLIED_PATCH_FILE} ]]; then
patch -p0< mypatch.patch
###  due to poco configure limit, we cannot point openssl binary at arbitrary place, the easiest way is to modify following poco make file "NetSSL_OpenSSL/Makefile" and "Crypto/Makefile"
###  replace line "SYSLIBS += -lssl -lcrypto" with the openssl-install
sed -i "s|SYSLIBS += -lssl -lcrypto|SYSLIBS += -L${BUILD_ROOT_DIR}/openssl-install -lssl -L${BUILD_ROOT_DIR}/openssl-install -lcrypto|g"   Crypto/Makefile
sed -i "s|SYSLIBS += -lssl -lcrypto|SYSLIBS += -L${BUILD_ROOT_DIR}/openssl-install -lssl -L${BUILD_ROOT_DIR}/openssl-install -lcrypto|g"   NetSSL_OpenSSL/Makefile
touch 
${APPLIED_PATCH_FILE}
fi
用脚本制作免passwd的ssh login这个我以前就看到paypal里是这么作的,使用ssh-copy-id要比手动拷贝文件可靠因为有的时候.ssh目录的安全属性很恼人的:
1.      ssh-keygen
Press Enter key till you get the prompt
2.      ssh-copy-id -i   your_user@ip_address
(It will once ask for the password of the host system)
Now you should be able to login without any password
如何检查你的显卡:
lspci -vnn | grep VGA -A 12
dmidecode -t baseboard | grep -i 'Product'
glxinfo | grep OpenGL

十二月十五日当前只有等待等待

工作中的动态库为了兼容两个版本导致统一路径下有两个几乎相同的动态库同时被server dynamic loading,当我在使用gdb的时候,gdb完全无知地总是选择第一个动态库的代码路径,我想这是因为你给的函数symbol在ld.so的搜寻算法 也是找的第一个match的结果,这个让人实在是有些头疼,同时动态库里的debug信息记录的代码文件路径也是取决于makefile的命令,比如我们 一开始是所有的makefile都是在顶级目录,这不符合一般开源的习惯,并且模块更新的时候总要调整,所以改为了嵌套的,那么相对路径就都不一样了,在 gdb里的directories命令的路径也就不一样了,总之远程debug实在是痛苦的事情。

十二月十八日当前只有等待等待

这个是一个很有意义的教训,就是直觉的问题,比如在svn的两个分支中(branch),我想生成他们之间的diff以便可以给用户用来patch从 branch1迁移到branch2,想当然的语法就是在较晚的那个branch2中使用如下svn diff -r rev1:rev2其中branch1的rev1比branch2的rev2来的小。这个在同一branch内或者trunk上完全没有问题,但是在不同 的branch1,2之间却不行。原本直觉是我可以应用最普通的diff做这件事,比如svn co -r re1 branch1-dir && svn co -r rev2 branch2-dir && diff -Naur -x .svn branch1-dir branch2-dir 这个做法肯定没有问题,但是效率很低,svn server一定有更快的做法,类似于git的fast forward的可以把rev1到rev2之间的所有的delta进行“累加”得到最终的结果。可是svn不行,至少1.7版不行,因为是不同的 branch期间有很多的checkin不在branch2内。这个看来是非常的against intuitive。把我都快逼疯了,后来K发现了正确的语法:svn diff -r1491:1805 --old=http://subversion.hds.com/sse_sie/Metro/branches/Metro-03_0_0 --new=http://subversion.hds.com/sse_sie/Metro/branches/Metro-03_1_0 > 3.1_to_3.0.patch 就是说你要“引导”svn采用之前我的想法,类似于全部checkout再作diff。这里推荐两个diff的工具,lsdiff可以显示diff里的包 含的文件名列表。而filterdiff可以删除不需要的diff文件,查看发现其中的被删除的文件还在diff里,只不过其中的index没有了,因此 patch就会忽略他们。
安装了google拼音,可是输入法导致了不少的问题,我到底是在使用Google拼音还是搜狗拼音呢?中英文切换变成了输入法切换?现在还在熟悉阶段.

十二月二十二日当前只有等待等待

这个是一个非常不同寻常的bug.首先故事的起源是这样的.我们的server采用dynamic loading,在初始化阶段作为优化首先把所有的shared library统统都load到内存里,然后server再等待client的请求,相应的从线程池分配线程来Handle request.这个流程随着有两个新加入的动态库发生deadlock,我于是使用gdb来跟踪发现发生死锁的情况是当请求到来的时候线程欲请求一个写 log的mutex的时候那个pthread_mutex_t已然被主线程所有,这是通过打印mutex的在gdb里看到thread id 是初始化的主线程的threadid.然后问题就是当主线程一旦把那个动态库load到内存结果mutex就初始化了而且这个count始终为1不再释 放.这里有些令人费解,因为我们的mutex都是使用标准的做法,在被调用函数里使用一个mutex的wrapper class来做的,比如
class MutexWrapper{
public:
MutexWrapper(pthread_mutex_t*ptr):m_ptr(ptr){ptrhead_mutex_lock(m_ptr);}
 ~MutexWrapper(){pthread_mutex_unlock(m_ptr);}
private:
pthread_mutex_t* m_ptr;
};
我这里是一个简化的实现来说明,所以在使用的时候典型的例子是:
pthread_mutex_t g_fastMutex = PTHREAD_MUTEX_INITIALIZER;
void some_critical_section_function(){
...
MutexWrapper(&g_fastMutex);
... // some critical section needs to be synchronized
}
这里的lock在程序超出范围自动触发destructor解锁绝无死锁的可能啊?而且当shared library一被dlopen/dlload到内存这个g_fastMutex的内部计数就是1实在是令人难以想像这个明显是全局变量的架势,可是我们 的MutexWrapper的使用都是在函数内部的临时i变量啊.而这样子的问题压根没法gdb因为在load前代码的symbol是不在内存的gdb无 法定位设断点,而一旦load也过了初始化了.这个真是个难题,唯一的办法就似乎只有用眼睛来看代码了.我想了很久最后决定从汇编码看看有没有什么线索, objdump -S并没有给你什么线索.于是就看preprocessor的输出:g++ -E obj.o终于看到了端倪,其实以上的代码都是示范而已,实际部分是使用了大量的宏而宏的定义出错了.比如
#define BEGIN_LOCK MutexWrapper mw(&g_fastMutex);
#define BEGIN_API SOME_OTHER_MACRO
     BEGIN_LOCK;
...
void some_critical_section_function(){
...
BEGIN_API
... // some critical section needs to be synchronized
}
注意在SOME_OTHER_MACRO后面程序员一时粗心忘了\结果后边的BEGIN_LOCK宏居然就定义了一个全局的lock,而且这个永远不会释放,因为他没有被用在stack里啊.

十二月二十三日当前只有等待等待

For Azeroth! For the Alliance!
Warcraft 我看了第五遍的时候终于感动的留下热泪.

十二月二十四日当前只有等待等待

在amazon上买了宝典The C++ Programming Language(4th edition)硬皮版开始阅读,不要以为这个是一本入门的闲书,其中的c++11部分让我从第一页就感觉吃力,因为c++11的新feature相当的 让人感到震惊,因为我虽然学习使用了c++十几年并不代表我对于其中的设计思想有多少思考,一个简单的prefix++和postfix++的重载就让我 僵在那里,postfix++的参数是一个无用的型参纯粹是用来区分函数的,我在读google到的问题时候,看到有人不理解以为是default parameter,这个想法还真有意思我就没有想到会有这个,当然是误解可是也是有道理的.有人回到说要看c++创建者的著名的D&E,我打算以后再看,下载了一个作者在2005的短文,似乎是一个简短的回忆?不妨留存一下.D&E如果好的话再买正版来读。

Smiley face