推动知识管理的这两年

掐指算来,部门知识管理的推广工作已有两年了。两年时间不能算短,但对于知识管理这件事来说,只能算是热身阶段,我们依旧站在起跑线上,或者稍乐 观地讲我们只是刚刚迈出了万米长跑的第一步。

下面是这两年来部门内部知识库建设的一个Timeline:

- 2011年中旬,我所在产品线私下在一台PC上建立了基于MediaWiki的知识库。
- 2011年末产品线在部门内部做了有关知识库与知识管理实践的分享。
- 2012年初,部门在新采购的高性能服务器上建立基于MediaWiki的知识库,并指定专人负责;我们产品线将已经积累的内容迁移到了部门知识库中,这 也标志着部门知识库1.0版本正式上线。知识管理的策划和推广事宜也交由专门的子部门负责。
- 2012年中,设立子部门KM负责人,设立子部门KM定期工作会,设立子部门技术交流汇报会,旨在各子部门之间分享最新信息,减少重复劳动,提高效率。
- 2012年末,启动知识库2.0建设方案。
- 2013年3月末,知识库2.0版本上线。邀请专业设计人员策划和实现了全新主页,提高了UE;重新策划了分类;重新划分了知识版块,专人负责更新;增加 了知识达人等多个激励内部童鞋分享知识的手段和方法;通过piwik统计和分析知识库的最新访问动态;通过一些实用的插件来简化Wiki Page编写工作、更好地展示内容;提炼高质量知识文章,形成知识周刊、月刊,作为内部知识库营销推广手段,吸引大家来到知识库,并尝试留下自己的知识。

两年来,我这个“始作俑者”在知识库建立起来后已经不做什么具体的工作了(骨子里其实是不愿意做重复性、事务性工作),只是充当着“幕后推手”。值得我庆幸的是有那么几位同事都认同知识管理 的重要性,愿意参与进来执行具体的工作。专职负责知识管理的子部门的领导也十分重视此事,这才有了部门知识库的持续演进,才有了目前的2.0版本 上线,他们才是真正的猪角。

这两年来,我在知识管理方面所作的工作主要有如下几方面:

* 找人,形成圈子

知识管理和推广虽然重要,但并非核心业务,不能显式地让大家看到其对部门发展的贡献度,因此多数人对此工作并不感兴趣,找到适合且对此有兴趣和热 情的人也就并非易事。另外还要得到相关子部门领导的长期支持,事情才好持续办下去。在1.0上线后,经过大半年的观察,我们找到了真正合适的人 选。也有两位志同道合的子部门领导十分重视此事,也亲自参与到知识库建设的交流讨论中。这样一个知识管理和推广的小圈子形成了。

* 识别广泛的需求,形成可行性共识

最初之所以在产品线私下建立起Wiki知识库,显然是因为我们遇到了诸多具体问题,诸如知识如何共享、知识的发现、知识更新以及一致性等(那时的 知识局限在项目过程中的各种文档资料等)。我们想通过一个共享的协作平台解决掉遇到的问题,于是有了我们自己的Wiki。这些问题其实是有共性 的,我们遇到了,其他产品线、开发组、子部门也会遇到。也就是说这个Wiki不仅仅能解决我们的问题,还能帮助解决其他人的问题。为此,我们做了 多次公开调查和私下交流,确定了知识库的必要性和大力推广的可行性。

* 保持与知识库的直接负责领导常沟通

我顶多算是一个“推手”,具体的知识库运营是由某子部门领导负责的。因此在用人以及知识库演进方面,还要常与领导沟通,达成一致后,推动执行起来 就方便的多了。

* 元策划

所谓的元策划就是为负责策划的具体执行人提供策划咨询,指导如何策划,仅此而已。当然有时也提供具体策划思路^_^。

* 监督实施

这个很关键。虽然我不直接负责知识管理这块,但我心目中是有一些期望达成的里程碑点的。因此我会不时的与具体的执行人了解进度情况,也算是一种督促和监督了。

知识库2.0上线一月有余,他们弄了个知识月刊首期,居然把我评为月度“知识达人”,还问我是否可以分享些知识积累和总结方面的心得。以前从未系统考虑过这个问题,冷不丁的提起来还真没啥思路。不过花些时间深入想了想,还是有点体会的,也许这个体会比较另类。

我承认我日常喜欢做一些知识积累和总结,只是喜欢并习惯为之而已,谈不上什么擅长,无论是工作中还是业余时间的学习过程中。为什么会这样呢?这么做到底动 机何为?我也仔细想了一下:从心理上来说这可能是源于一种“忧患意识”吧。真的是忧患:担心记性差,导致设计思路等知识和技巧的遗忘,那可真是种浪费和损 失;担心无地儿去回顾/查找(因此要起个好标题,找个好分类,贴上适当标签);担心体验和心得的消失;担心自己每天没有进步(一直追求每天进步一点点,而 积累和总结则是一种显式地进步的体现);担心别人看不到自己最新更新的内容(因此放到Wiki这种载体);担心大脑容量不够,无法装得下那么多内容,所以 持久化到一类“永恒”的介质(blog、wiki)中;担心自己说不清楚,讲不明白,就写下来,并反复揣摩修改,直到自己满意;担心太多的东西放在大脑 中,太沉重,无法轻装前进,因此写出来,腾出一些空间,容纳点新东西等等。

两年了,还是那句话,自己在知识管理方面依旧是野路子+新手!估计自己以后依旧不会直接做知识管理方面的执行工作,但肯定会是一个知识分享者以及一个旁观 参与者。知识库的建立为组织内的每个人、项目、产品线、子部门提供了一个分享的平台,也是一个自我展示的平台。知识库的内部营销才刚刚上路,前途光明,道 路坎坷,猪脚们要有一颗耐心。

最后和大家分享一下我们知识库的slogan:“知识不怕从头积累,就怕从不积累”

libiconv库链接问题一则

与在Solaris系统上不同,Linux的libc库中包含了libiconv库中函数的定义,因此在Linux上使用libiconv库相关函数,编译时是不需要显式-liconv的。但最近我的一位同事在某redhat enterprise server 5.6机器上编译程序时却遇到了找不到iconv库函数符号的链接问题,到底是怎样一回事呢?这里分享一下问题查找过程。

一、现场重现

这里借用一下这位同事的测试程序以及那台机器,重现一下问题过程:
/*test.c */


#include <iconv.h>

int main(void)
{
    int r;
    char *sin, *sout;
    size_t lenin, lenout;
    char *src = "你好!";
    char dst[256] = {0};
    iconv_t c_pt;  

    sin = src;
    lenin = strlen(src)+1;

    sout = dst;
    lenout = 256;

    if ((c_pt = iconv_open("UTF-8", "GB2312")) == (iconv_t)(-1)){
        printf("iconv_open error!. errno[%d].\n", errno);
        return -1;
    }

    if ((r = iconv(c_pt, (char **)&sin, &lenin, &sout, &lenout)) != 0){
        printf("iconv error!. errno[%d].\n", r);
        return -1;
    }  

    iconv_close(c_pt);

    printf("SRC[%s], DST[%s].\n", src, dst);

    return 0;
}

根据之前的经验,我们按如下命令编译该程序:

$> gcc -g -o test test.c

/tmp/ccyQ5blC.o: In function `main':
/home/tonybai/tmp/test.c:28: undefined reference to `libiconv_open'
/home/tonybai/tmp/test.c:33: undefined reference to `libiconv'
/home/tonybai/tmp/test.c:38: undefined reference to `libiconv_close'

咦,这是咋搞的呢?怎么找不到iconv库的符号!!!显式加上iconv的链接指示再试试。

$> gcc -g -o test test.c -liconv

这回编译OK了。的确如那位同事所说出现了怪异的情况。

二、现场取证

惯性思维让我首先提出疑问:难道是这台机器上的libc版本有差异,检查一下libc中是否定义了iconv相关符号。

$ nm /lib64/libc.so.6 |grep iconv
000000397141e040 T iconv
000000397141e1e0 T iconv_close
000000397141ddc0 T iconv_open

iconv的函数都定义了呀!怎么会链接不到?

我们再来看看已经编译成功的那个test到底连接到哪个iconv库了。

$ ldd test
    linux-vdso.so.1 =>  (0x00007fff77d6b000)
    libiconv.so.2 => /usr/local/lib/libiconv.so.2 (0x00002abbeb09e000)
    libc.so.6 => /lib64/libc.so.6 (0×0000003971400000)
    /lib64/ld-linux-x86-64.so.2 (0×0000003971000000)

哦,系统里居然在/usr/local/lib下面单独安装了一份libiconv。gcc显然是链接到这里的libiconv了,但gcc怎么会链接到这里了呢?

三、大侦探的分析^_^

Gcc到底做了什么呢?我们看看其verbose的输出结果。

$ gcc -g -o test test.c -liconv -v
使用内建 specs。
目标:x86_64-redhat-linux
配置为:../configure –prefix=/usr –mandir=/usr/share/man –infodir=/usr/share/info –enable-shared –enable-threads=posix –enable-          checking=release –with-system-zlib –enable-__cxa_atexit –disable-libunwind-exceptions –enable-libgcj-multifile –enable-languages=c,c++,   objc,obj-c++,java,fortran,ada –enable-java-awt=gtk –disable-dssi –disable-plugin –with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre –with-cpu=generic –host=x86_64-redhat-linux
线程模型:posix
gcc 版本 4.1.2 20080704 (Red Hat 4.1.2-50)
 /usr/libexec/gcc/x86_64-redhat-linux/4.1.2/cc1 -quiet -v test.c -quiet -dumpbase test.c -mtune=generic -auxbase test -g -version -o /tmp/     ccypZm0v.s
忽略不存在的目录“/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../x86_64-redhat-linux/include”
#include "…" 搜索从这里开始:
#include <…> 搜索从这里开始:
 /usr/local/include
 /usr/lib/gcc/x86_64-redhat-linux/4.1.2/include
 /usr/include
搜索列表结束。
GNU C 版本 4.1.2 20080704 (Red Hat 4.1.2-50) (x86_64-redhat-linux)
    由 GNU C 版本 4.1.2 20080704 (Red Hat 4.1.2-50) 编译。
GGC 准则:–param ggc-min-expand=100 –param ggc-min-heapsize=131072
Compiler executable checksum: ef754737661c9c384f73674bd4e06594
 as -V -Qy -o /tmp/ccaqvDgX.o /tmp/ccypZm0v.s
GNU assembler version 2.17.50.0.6-14.el5 (x86_64-redhat-linux) using BFD version 2.17.50.0.6-14.el5 20061020
 /usr/libexec/gcc/x86_64-redhat-linux/4.1.2/collect2 –eh-frame-hdr -m elf_x86_64 –hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.  2 -o test /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crti.o /usr/   lib/gcc/x86_64-redhat-linux/4.1.2/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.1.2 -L/usr/lib/gcc/x86_64-redhat-linux/4.1.2 -L/usr/lib/gcc/ x86_64-redhat-linux/4.1.2/../../../../lib64 -L/lib/../lib64
-L/usr/lib/../lib64 /tmp/ccaqvDgX.o -liconv -lgcc –as-needed -lgcc_s –no-as-needed -lc -lgcc –as-needed -lgcc_s –no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.1.2/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crtn.o

从这个结果来看,gcc在search iconv.h这个头文件时,首先找到的是/usr/local/include/iconv.h,而不是/usr/include/iconv.h。这两个文件有啥不同么?

在/usr/local/include/iconv.h中,我找到如下代码:


#ifndef LIBICONV_PLUG
#define iconv_open libiconv_open
#endif
extern iconv_t iconv_open (const char* tocode, const char* fromcode);

libiconv_open vs iconv_open,卧槽!!!再对比一下前面编译时输出的错误信息:

/tmp/ccyQ5blC.o: In function `main':
/home/tonybai/tmp/test.c:28: undefined reference to `libiconv_open'
/home/tonybai/tmp/test.c:33: undefined reference to `libiconv'
/home/tonybai/tmp/test.c:38: undefined reference to `libiconv_close'

大侦探醒悟了!大侦探带你还原一下真实情况。

我们在执行gcc -g -o test test.c时, 根据gcc -v中include search dir的顺序,gcc首先search到的是/usr/local/include/iconv.h,而这里iconv_open等函数被预编译器替换成 了libiconv_open等加上了lib前缀的函数,而这些函数符号显然在libc中是无法找到的,libc中只有不带lib前缀的 iconv_open等函数的定义。大侦探也是一时眼拙了,没有细致查看gcc的编译错误信息中的内容,这就是问题所在!

gcc -g -o test test.c -liconv为何可以顺利编译通过呢?gcc是如何找到/usr/local/lib下的libiconv的呢?大侦探再次为大家还原一下真相。

我们在执行gcc -g -o test test.c -liconv时,gcc同 样首先search到的是/usr/local/include/iconv.h,然后编译test.c源码,ok;接下来启动ld程序进行链接;ld找 到了libiconv,ld是怎么找到iconv的呢,libiconv在/usr/local/lib下,ld显然是到这个目录下search了。我们 通过执行下面命令可以知晓ld的默认搜索路径:

$> ld -verbose|grep SEARCH
SEARCH_DIR("/usr/x86_64-redhat-linux/lib64"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/x86_64-redhat-linux/lib"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");

ld的默认search路径中有/usr/local/lib(我之前一直是以为/usr/local/lib不是gcc/ld的默认搜索路径的),因此找到libiconv就不足为奇了。

四、问题解决

我们不想显式的加上-liconv,那如何解决这个问题呢?我们是否可以强制gcc先找到/usr/include/iconv.h呢?我们先来做个试验。

$ gcc -g -o test test.c -liconv -I ~/include -v

忽略不存在的目录“/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../x86_64-redhat-linux/include”
#include "…" 搜索从这里开始:
#include <…> 搜索从这里开始:
 /home/tonybai/include
 /usr/local/include
 /usr/lib/gcc/x86_64-redhat-linux/4.1.2/include
 /usr/include
搜索列表结束。

试验结果似乎让我们觉得可行,我们通过-I指定的路径被放在了第一的位置进行search。我们来尝试一下强制gcc先search /usr/include。

$ gcc -g -o test test.c -I ~/include -v

忽略不存在的目录“/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../x86_64-redhat-linux/include”
忽略重复的目录“/usr/include”
  因为它是一个重复了系统目录的非系统目录
#include "…" 搜索从这里开始:
#include <…> 搜索从这里开始:
 /usr/local/include
 /usr/lib/gcc/x86_64-redhat-linux/4.1.2/include
 /usr/include
搜索列表结束。

糟糕!/usr/include被忽略了!还是从/usr/local/include开始,方案失败。

似乎剩下的唯一方案就是将/usr/local/lib下的那份libiconv卸载掉!那就这么做吧^_^!

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats